F. PolandBall and Gifts 題解(貪心+二進位制優化多重揹包+bitset)
阿新 • • 發佈:2021-08-23
題目連結
題目思路
如何最大化收不到禮物的人數?對於一個偶環,假設長度為 k。那麼只要有 k / 2 個人忘帶禮物,k 個人就全都收
不到禮物。對於一個奇環,假設長度為 k。那麼需要有 (k + 1) / 2 個人忘帶禮物,k 個人就會都收不到禮物。貪心
即可。
如何最小化收不到禮物的人數?如果有一個大小為 m 的環,只要讓這 m 個人都忘帶,就只會有 m 個人收不到禮
物。因此如果能找到若干個環,使得它們的長度之和剛好是 k,那麼答案就是 k。否則會有一個環不能被完全覆
蓋,還會再牽連一個人,答案就是 k + 1
這個可以用二進位制優化dp 那麼複雜度最壞為\(n\sqrt n\) 但是有點卡常 對於存不存在問題用個\(bitset\)
最後的複雜度為\(\frac{n\sqrt n}{w}\)
程式碼
卷也卷不過,躺又躺不平#include<bits/stdc++.h> #define fi first #define se second #define debug printf(" I am here\n"); using namespace std; #define S dp typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll> pii; mt19937 rnd(time(0)); const ll INF=0x3f3f3f3f3f3f3f3f; const int maxn=1e6+5,inf=0x3f3f3f3f,mod=1e9+7; const double eps=1e-10; int n,k; int a[maxn],vis[maxn]; int num[maxn]; int cnt,tot; int ma,mi; bitset<maxn> dp; signed main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<=n;i++){ if(vis[i]) continue; int x=i,sum=0; while(!vis[x]){ vis[x]=1; x=a[x]; sum++; } num[sum]++; if(sum%2==1) tot++; } if(2*k<=n-tot){ ma=2*k; }else{ ma=min(n,(n-tot)+(k-(n-tot)/2)); } dp[0]=1; for(int i=1;i<=1e6;i++){ if(num[i]==0) continue; vector<int> vec; for(int j=0;(1<<j)<=num[i];j++){ vec.push_back(1<<j); num[i]-=(1<<j); } if(num[i]){ vec.push_back(num[i]); } for(auto x:vec){ dp=(dp|(dp<<x*i)); } } if(dp[k]){ mi=k; }else{ mi=k+1; } printf("%d %d\n",mi,ma); return 0; }