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);
    
}
View Code

 

posted @ 2022-05-24 19:57  VxiaohuanV  阅读(37)  评论(0编辑  收藏  举报