CF1951H Thanos Snap 题解
题目链接:CF1951H Thanos Snap
考虑一个区间如果还要被 Bob 划分 $ k $ 次,那么这个区间至少还得有 $ 2^k $ 个 $ \texttt{1} $,然后发现这个条件很充分的样子,于是枚举 $ k $,然后直接 $ dp $ 即可,$ dp $ 状态只有一位即当前节点,然后存储的是使得当前区间需要的最小操作数,最底层如果区间内有至少一个 $ \texttt{1} $ 就是 $ \texttt{0} $,否则是 $ \texttt{1} $,转移就是左区间加右区间减一和当前区间缺的 $ \texttt{1} $ 数量取 $ \max $,时间复杂度 $ O(nlog^2n) $。
为什么是对的(可以直接减一)?因为如果 $ \texttt{1} $ 的数量充足,直接从这一层的左(右)区间移一个 $ \texttt{1} $ 到右(左)区间即可( $ \texttt{1} $ 的数量仍够)。
代码:
#include<bits/stdc++.h>
#define time(null) chrono::steady_clock::now().time_since_epoch().count()
#define int long long
#define uint unsigned long long
#define debug() cout<<"come here\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define pb push_back
#define Code return
#define by 0
#define MCYYDS ;
using namespace std;
int qpow(int a,int b,int p=INF){int ret=1;while(b){if(b&1)ret=(ret*a)%p;a=(a*a)%p;b>>=1;}return ret;}
inline int read(){int ret=0,f=1;char ch=getchar();while(ch<'0'||ch>'9')f=(ch=='-'?-1:f),ch=getchar();while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();return ret*f;}
inline void write(int x){if(x<0){putchar('-');write(-x);return ;}if(x>9)write(x/10);putchar((char)(x%10+48));}
inline void writech(int x,char ch){write(x);putchar(ch);}
int k,n,a[2000005],dp[4000005],s[2000005];
void dfs(int l,int r,int id,int v)
{
if(r-l+1==(1<<v))
{
dp[id]=(s[r]-s[l-1]==0);
return ;
}
int mid=l+r>>1;
dfs(l,mid,id<<1,v);
dfs(mid+1,r,id<<1|1,v);
dp[id]=max(0ll,max(dp[id<<1]+dp[id<<1|1]-1,((r-l+1)>>v)-s[r]+s[l-1]));
}
bool check(int x,int v)
{
for(int i=1;i<=n;i++)
{
s[i]=s[i-1]+(a[i]>=x);
}
dfs(1,n,1,k-v);
return (dp[1]==0);
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int T=read();
while(T--)
{
k=read(),n=(1<<k);
for(int i=1;i<=n;i++)
{
a[i]=read();
}
for(int i=1;i<=k;i++)
{
int l=1,r=n,ans;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid,i))l=mid+1,ans=mid;
else r=mid-1;
}
writech(ans,' ');
}
puts("");
}
Code by MCYYDS
}

浙公网安备 33010602011771号