题解 P5592 【美德的讲坛】
结合了最小割,贪心,甚至还有点模拟费用流的贪心思想(((
首先有最小割模型,将所有
对应到
注意到最小割即为网络流,若
否则,若当前位权值为
若
若
否则,以
注意到修改时只会修改
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7,M=1e7+7; bool fl[M];
int n,q,tot,dep[M],siz[M],ans[M],ch[M][2];
long long k,w[N];
inline long long read(){
long long num=0; char g=getchar(); while(g<48||57<g) g=getchar();
while(47<g&&g<58) num=(num<<1)+(num<<3)+g-48,g=getchar(); return num;
}
inline void write(int u){
if(u>9) write(u/10); putchar(u%10+'0');
}
inline void ins(int u,long long k){
siz[u]++,fl[u]=0; if(dep[u]<0) return;
if(k&(1ll<<dep[u])){
if(!ch[u][1]) ch[u][1]=++tot,dep[tot]=dep[u]-1; ins(ch[u][1],k);
}
else{
if(!ch[u][0]) ch[u][0]=++tot,dep[tot]=dep[u]-1; ins(ch[u][0],k);
}
}
inline void del(int u,long long k){
siz[u]--,fl[u]=0; if(dep[u]<0) return;
if(k&(1ll<<dep[u])) del(ch[u][1],k); else del(ch[u][0],k);
}
inline int getans(int u,int v){
if(!siz[u]||!siz[v]) return 0;
if(dep[u]<0){
if(u==v) return ans[u]=siz[u]-(siz[u]&1); return ans[u]=min(siz[u],siz[v]);
}
if(fl[u]&&fl[v]) return ans[u]; fl[u]=1,fl[v]=1;
if(k&(1ll<<dep[u])){
if(u==v) ans[u]=ans[v]=getans(ch[u][0],ch[v][1]);
else ans[u]=ans[v]=getans(ch[u][0],ch[v][1])+getans(ch[u][1],ch[v][0]);
return ans[u];
}
else{
int fq=getans(ch[u][0],ch[v][0]),fw=getans(ch[u][1],ch[v][1]);
if(u==v) ans[u]=fq+fw+min(siz[ch[u][0]]-fq,siz[ch[v][1]]-fw);
else if(siz[ch[u][0]]<=siz[ch[v][1]]&&siz[ch[u][1]]<=siz[ch[v][0]]) ans[u]=siz[ch[u][0]]+siz[ch[u][1]];
else if(siz[ch[u][0]]>=siz[ch[v][1]]&&siz[ch[u][1]]>=siz[ch[v][0]]) ans[u]=siz[ch[v][0]]+siz[ch[v][1]];
else if(siz[ch[u][0]]<=siz[ch[v][1]]&&siz[ch[u][1]]>=siz[ch[v][0]]){
fw=min(min(fw,siz[ch[v][1]]-siz[ch[u][0]]),siz[ch[u][1]]-siz[ch[v][0]]);
ans[u]=fw+siz[ch[u][0]]+siz[ch[v][0]];
}
else{
fq=min(min(fq,siz[ch[v][0]]-siz[ch[u][1]]),siz[ch[u][0]]-siz[ch[v][1]]);
ans[u]=fq+siz[ch[u][1]]+siz[ch[v][1]];
}
ans[v]=ans[u]; return ans[u];
}
}
int main(){
n=read(),q=read(),k=read(),dep[1]=60,tot=1; int c;
for(int i=1;i<=n;i++) w[i]=read(),ins(1,w[i]);
write(max(n-getans(1,1),1)),putchar('\n');
for(int i=1;i<=q;i++)
c=read(),del(1,w[c]),w[c]=read(),ins(1,w[c]),write(max(n-getans(1,1),1)),putchar('\n');
return 0;
}