1.Problem - A - Codeforces
这道题感觉网上的题解都讲得非常复杂,但是也给了我一些启发,最后a出来后发现并没有那么困难,首先这题假设我们的答案是x,那么就代表有(sum + k) / x个牌堆,想要让x合法需要满足两个条件
1.(sum + k) / x >= maxn,因为每副牌堆不能有重复的牌,那么牌堆数至少要大于等于最多的牌才有可能
2.(sum + k) / x * x >= sum,这是因为当k = 0的时候sum / x是向下取整的,此时有可能出现牌堆数 * x < sum的情况,这是不能存在的
#define yyy cout<<"Yes"<<"\n"
#define nnn cout<<"No"<<"\n"
#define x first
#define y second
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
typedef pair<ll , ll> pii;
typedef pair<int , string> pis;
const int N = 1e6 + 10,M = 2e5 + 5e4,inf = 0x3f3f3f3f,mod = 1e9 + 7;
const double pi = 3.1415926535898;ll n,k;
ll a[N];void work()
{cin>>n>>k;ll maxn = 0,sum = 0;for(int i = 1 ; i <= n ; i++){cin>>a[i];maxn = max(maxn , a[i]);sum += a[i];}int ans = 1;for(int i = n ; i >= 1 ; i--){ll y = (sum + k) / i;if(y >= maxn && y * i >= sum){ans = i;break;}}cout<<ans<<"\n";
}int main()
{std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);int t;cin>>t;while(t--){work();}
}
2.D - Project Planning
想复杂了,这题可以直接二分答案,因为我们发现只要场次够小就一定可以满足,而若是超过一个临界值就无法满足,因此我们需要二分找出这个临界值,那么如何判断能不能凑出mid场呢,对于ai >= mid的计数+1,而对于ai < mid的则需要所有ai < mid的凑起来一起除去mid是他们的贡献数看加起来是否超过k
#define yyy cout<<"Yes"<<"\n"
#define nnn cout<<"No"<<"\n"
#define x first
#define y second
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
typedef pair<ll , ll> pii;
typedef pair<int , string> pis;
const int N = 5e5 + 10,M = 2e5 + 5e4,inf = 0x3f3f3f3f,mod = 1e9 + 7;
const double pi = 3.1415926535898;ll n,k;
ll a[N];bool check(ll mid)
{ll sum = 0,cnt = 0;for(int i = 1 ; i <= n ; i++){if(a[i] >= mid){cnt++;}else{sum += a[i];}}cnt += sum / mid;return cnt >= k;
}int main()
{std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);cin>>n>>k;for(int i = 1 ; i <= n ; i++){cin>>a[i];}ll l = 0,r = 1e18;while(l < r){ll mid = (l + r + 1) / 2;if(check(mid)){l = mid;}else{r = mid - 1;}}cout<<r;
}
3.P1197 [JSOI2008] 星球大战 - 洛谷 | 计算机科学教育新生态
正难则反,首先很容易能够想到并查集,但是对于删点的操作不太好想,因为我们每次删除一个点i我们并不能知道与i相连的j是否还与其他点有连结从而继续联通,但是我们反过来想,不是将k个点依次删除而是从头到尾将k个点依次连结,这样每次接点的时候只需要i和j的祖先是否相同,若不同则合并后一定会少一个连通块,复杂度实际上是k + m
#define yyy cout<<"Yes"<<"\n"
#define nnn cout<<"No"<<"\n"
#define x first
#define y second
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
typedef pair<ll , ll> pii;
typedef pair<int , string> pis;
const int N = 1e6 + 10,inf = 0x3f3f3f3f,mod = 1e9 + 7;
const double pi = 3.1415926535898;int n,m,k;
int p[N],a[N],ans[N];
vector <int> g[N];
bool st[N];int find(int x)
{if(p[x] != x){p[x] = find(p[x]);}return p[x];
}void merge(int u,int v)
{int fu = find(u),fv = find(v);if(fu != fv){p[fu] = fv;}
}int main()
{std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);cin>>n>>m;for(int i = 0 ; i < n ; i++){p[i] = i;}for(int i = 1 ; i <= m ; i++){int u,v;cin>>u>>v;g[u].push_back(v);g[v].push_back(u);}int k;cin>>k;for(int i = 1 ; i <= k ; i++){cin>>a[i];st[a[i]] = 1;}int sum = n - k;for(int i = 0 ; i < n ; i++){int u = i;if(st[u]){continue;}for(int j = 0 ; j < g[u].size() ; j++){int v = g[u][j];if(st[v]){continue;}int fu = find(u),fv = find(v);if(fu != fv){sum--;merge(fu , fv);}}}ans[k] = sum;for(int i = k ; i >= 1 ; i--){int u = a[i];sum++,st[u] = 0;for(int j = 0 ; j < g[u].size() ; j++){int v = g[u][j];if(st[v]){continue;}int fu = find(u),fv = find(v);if(fu != fv){sum--;merge(fu , fv);}}ans[i - 1] = sum;}for(int i = 0 ; i <= k ; i++){cout<<ans[i]<<"\n";}
}