Codeforces Round 936 (Div. 2) (A~C)
前言
写的时候B题题意读错了,C题二分边界调歪了又没注意到,心态大崩,美美掉分......
D题之后补完再更新吧。
A. Median of an Array 贪心
发现原数组顺序没有用,显然先进行一个排序,找中位数的点,往后遍历找与中位数相同的有多少个,全部加一就可以实现最后落到中位数位置的数一定变大。
void solve(int ce){
cin >> n;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
int cnt = 1;
sort(a + 1, a + n + 1);
for(int i = (n + 1)/2 + 1;i <= n; i++){
if(a[(n + 1)/2] == a[i]){
cnt++;
}
else break;
}
cout << cnt << endl;
}
B. Maximum Sum 贪心
题意是每次操作选取一个任意连续子数组和,然后把和插到原数组任意位置,然后求K次操作后最大数组和。
一开始被取模迷惑了以为是求数组和取模后最大,绞尽脑汁了半天
只用求一个最大子数组和,然后每次把这个和插入到原来子数组里,如果这个子数组和比原来小,那就不操作。
void solve(int ce){
cin >> n >> k;
int ans = 0,sum = 0;
for(int i = 1; i <= n; i++){
cin >> a[i];
ans += a[i];
}
int res=-INF;
dp[0]=0;
for(int i=1;i <= n; i++){
dp[i]=max(dp[i - 1] + a[i],a[i]);
res = max(dp[i],res);
}
sum = res;
if(sum <= 0){
cout << ((ans % mod) + mod) % mod << endl;
}
else {
ans -= sum;
ans = ((ans % mod) + mod) % mod;
for(int i = 1; i <= k; i++){
sum = sum * 2 % mod;
}
cout << (ans + sum + mod) % mod << endl;
}
}
C. Tree Cutting 二分,贪心
题意是把一棵树分成\(k\)个连通块,使得最小那个最大。
二分答案,然后用\(dfs\)进行\(check\),如果这个子树大小 \(\geqslant mid\) 那么将当前子树断开,即把当前结点子树大小改为\(0\),连通块个数加一。比较连通块个数和\(k\)
int dp[N];
int res = 0;
vector<int> g[N];
void dfs(int u, int fa, int x){
dp[u] = 1;
for(auto v : g[u])if(v != fa){
dfs(v, u, x);
dp[u] += dp[v];
}
if(dp[u] >= x){
res++;
dp[u] = 0;
}
}
void solve(int ce){
cin >> n >> k;
for(int i = 1, u, v; i < n; i++){
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
int l = 1, r = n;
while(l < r){
res = 0;
int mid = l + r >> 1;
dfs(1, 0, mid);
if(res > k){
l = mid + 1;
}
else r = mid - 1;
}
int ans = 1;
for(int i = max(1ll, l - 1); i <= min(n, l); i++){
res = 0;
dfs(1, 0, i);
if(res > k){
ans = i;
}
}//小规模暴力了一下,省的调边界
cout << ans << endl;
for(int i = 1; i <= n; i ++){
g[i].clear();
}
}

浙公网安备 33010602011771号