do NOT a=2b (DP)
swjtu—春季集训 - Virtual Judge (vjudge.net)
题目:NEVER,NEVER,NEVER have a = 2ba=2b in an array!,删最小的数目,满足条件
思路:
- 开始想用贪心给每一个点赋一个权值,在用优先队列--修改版本,去解决
- 发现改了,很多次,大数据过不了
- 于是换思路,发现和DP有线性地推关系, 1,2, 4,8,16, 选与不选问题。
- 当然还有 其他的 3,6,12 啥的,没有2倍关系的就不管
- 具体看代码

#include <bits/stdc++.h> using namespace std; #define ri register int #define M 2000005 template <class G> void read(G &x) { x=0;int f=0;char ch=getchar(); while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x=f?-x:x; return ; } int n; int p[M]; int dp[M][3]; int num[M]; int vis[M]; int ans; void dfs(int a) { vis[a]=1; if(num[a*2]==0) return ; dp[a][1]=0; dp[a][0]=num[a]; a=a*2; while(1) { vis[a]=1; dp[a][1]=dp[a/2][0]; dp[a][0]=min(dp[a/2][0],dp[a/2][1])+num[a]; if(num[a*2]==0) { ans+=min(dp[a][1],dp[a][0]); break; } a=a*2; } } int main(){ read(n); for(ri i=1;i<=n;i++) { read(p[i]); num[p[i]]++; } sort(p+1,p+1+n); for(ri i=1;i<=n;i++) { if(vis[p[i]]) continue; dfs(p[i]); } printf("%d",ans); }