牛客编程巅峰赛S2第4场 - 钻石&王者
A 牛牛摆玩偶
需要放置个 物品,每个物品都必须放在合法区间内,每个位置只能放一个物品。有
个互不相交的区间
,题目希望相邻物品之间的距离的最小值越大越好,请输出这个值。
思路
二分答案,
或者
来
。
我的做法貌似麻烦了一点,问题不大,欢迎提出你的做法。
因为区间两两不相交,但是我又不确定区间是否有序,所以我把区间左右端点全部用一个set保存起来,并记录一下是左端点还是右端点。
然后记录一下上一个玩偶放置的位置,用
找到下一个可以放的位置:
- 如果是左端点,这一个就放在这里
- 如果是右端点,这一个就放在
看是否放置了
个玩偶。
#define fi first
#define se second
#define mk make_pair
#define o2(x) (x) * (x)
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define clr(a, b) memset((a), (b), sizeof((a)))
#define GKD std::ios::sync_with_stdio(false);cin.tie(0)
#define rep(i, s, t) for(int i = (s), LIM=(t); i < LIM; ++i)
#define per(i, s, t) for(int i = (s), LIM=(t); i >= LIM; --i)
#define my_unique(x) sort(all(x)), x.erase(unique(all(x)), x.end())
typedef long long LL;
typedef long long int64;
typedef unsigned long long uint64;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;// 998244353
const int MXN = 2e5 + 5;
const int maxn = 2e5 + 7;
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型 玩偶数
* @param m int整型 区间数
* @param intervals Interval类vector 表示区间
* @return int整型
*/
int doll(int n, int m, vector<Interval>& intervals) {
// write code here
LL L = 1, R = 1e10, mid, ans = 0;
set<pii> mp;
for(Interval x: intervals) {
mp.insert(mk(x.start, 1));
mp.insert(mk(x.end, 2));
}
auto check = [&](int mid) {
LL L = -1e11;
int cnt = 0;
while(cnt < n) {
auto p = mp.lower_bound(mk(L + mid, 0));
if(p == mp.end()) return false;
if((*p).se == 1) {
++ cnt;
L = (*p).fi;
}else if((*p).se == 2) ++ cnt, L = L + mid;
}
return cnt == n;
};
while(L <= R) {
mid = (L + R) >> 1;
if(check(mid)) ans = mid, L = mid + 1;
else R = mid - 1;
}
return (int)ans;
}
}; B 交叉乘
给你个数
,多次询问,每次询问给你
,输出
的值模
1000000007。
思路
算贡献经典老题。
将答案补全为:。
预处理出
。
再预处理
。
然后就可以回答答案了。
#define fi first
#define se second
#define mk make_pair
#define o2(x) (x) * (x)
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define clr(a, b) memset((a), (b), sizeof((a)))
#define GKD std::ios::sync_with_stdio(false);cin.tie(0)
#define rep(i, s, t) for(int i = (s), LIM=(t); i < LIM; ++i)
#define per(i, s, t) for(int i = (s), LIM=(t); i >= LIM; --i)
#define my_unique(x) sort(all(x)), x.erase(unique(all(x)), x.end())
typedef long long LL;
typedef long long int64;
typedef unsigned long long uint64;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;// 998244353
const int MXN = 2e5 + 5;
const int maxn = 2e5 + 7;
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 多次求交叉乘
* @param a int整型vector a1,a2,...,an
* @param query int整型vector l1,r1,l2,r2,...,lq,rq
* @return int整型vector
*/
vector<int> getSum(vector<int>& a, vector<int>& query) {
// write code here
int n = a.si***t)query.size() / 2;
vector<LL> suf(n + 1, 0), pre(n, 0), pre2(n, 0);
per(i, n - 1, 0) {
suf[i] = suf[i + 1] + a[i], suf[i] %= mod;
if(i != n - 1) pre[i] = a[i] * suf[i + 1] % mod;
}
rep(i, 1, n) pre[i] = (pre[i] + pre[i - 1]) % mod;
pre2[0] = a[0];
rep(i, 1, n) pre2[i] = (pre2[i - 1] + a[i]) % mod;
vector<int> ans, q(query);
while(m --) {
int R = q.back() - 1; q.pop_back();
int L = q.back() - 1; q.pop_back();
LL res = pre[R] - (L == 0? 0: pre[L - 1]);
res %= mod;
LL res2 = pre2[R] - (L == 0? 0: pre2[L - 1]);
res2 %= mod;
LL hou = 0;
if(R != n - 1) hou = suf[R + 1];
res = (res - res2 * hou % mod) % mod;
res = (res + mod) % mod;
ans.push_back((int)res);
}
reverse(all(ans));
return ans;
}
}; C 回家
二维矩阵内,每个格子住了一个人,初始矩阵为空,给出
个人回家顺序,每个人可以从矩阵边缘的任意一点出发,
4联通方式走回家,一个人完全回家后另一个人才能出发。回家的时候尽量不经过有人的格子,经过一次有人的格子他的沮丧值加,我希望所有人沮丧值之和最小,输出这个值。

京公网安备 11010502036488号