uoj176 新年的繁榮
阿新 • • 發佈:2019-01-18
pac 高位到低位 所有權 過程 合並 uoj main http time
鏈接:http://uoj.ac/problem/176
對於這種邊權難以直接維護的都直接考慮brouvka算法。
顯然,我們要做的是實現一個可以查詢&x最大的數據結構。
可以先對於所有權值建立一顆01-trie樹。
考慮在trie樹查詢答案的過程,可以考慮一個從高位到低位的貪心。
當x的第i位為1時,最優策略一定是能走1就走1。
當x的第i位為0時,既可以走0也可以走1。
因此可以用一個類似線段樹合並的方式,把每一個trie樹上的節點右兒子合並到左兒子上。
然後直接按照brouvka算法的套路搞一下就行了。
#include<iostream> #include<cctype> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<ctime> #include<set> #include<cstdlib> #include<algorithm> #define N 220000 #define L 200000 #define M 8000000 #define eps 1e-7 #define inf 1e9+70 #define db double #define ll long long #define ldb long double using namespace std; inline int read() { char ch=0; int x=0,flag=1; while(!isdigit(ch)){ch=getchar();if(ch==‘-‘)flag=-1;} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();} return x*flag; } int v[N],f[N]; int find(int x){if(x!=f[x])f[x]=find(f[x]);return f[x];} void merge(int x,int y){f[find(x)]=find(y);} struct node{int x,y;}w[N],p[N]; bool operator<(node a,node b) { if(a.y!=b.y)return a.y<b.y; else return a.x<b.x; } int n,m,a[N]; struct Trie { #define lson lc[o] #define rson rc[o] int size,root,lc[M],rc[M],maxv[M],mixv[M]; int newnode() { int o=++size; lson=rson=0;maxv[o]=mixv[o]=-inf; return o; } void upd(int x,int y) { if(!x||!y)return; if(maxv[x]==maxv[y])mixv[x]=max(mixv[x],mixv[y]); if(maxv[x]<maxv[y])mixv[x]=max(mixv[x],max(maxv[x],mixv[y])); if(maxv[x]>maxv[y])mixv[x]=max(mixv[x],maxv[y]); maxv[x]=max(maxv[x],maxv[y]); } void pushup(int o) { maxv[o]=mixv[o]=-inf; upd(o,lson);upd(o,rson); } void insert(int &o,int t,int x,int id) { if(!o)o=newnode(); if(!t) { if(maxv[o]>id)mixv[o]=max(mixv[o],id); if(maxv[o]<id)mixv[o]=maxv[o],maxv[o]=id; return; } if(!((1<<(t-1))&x))insert(lson,t-1,x,id); else insert(rson,t-1,x,id); pushup(o); } int merge(int x,int y) { if(!x||!y)return x|y; int o=newnode(); lson=merge(lc[x],lc[y]); rson=merge(rc[x],rc[y]); maxv[o]=mixv[o]=-inf; upd(o,x);upd(o,y); return o; } void solve(int o,int t) { if(!t||!o)return; if(lson)solve(lson,t-1); if(rson)solve(rson,t-1); lson=merge(lson,rson); } node query(int o,int t,int x,int id) { if(!t)return (node){(id==maxv[o])?mixv[o]:maxv[o],0}; if((1<<(t-1))&x) { if((!rson)||(id==maxv[rson]&&mixv[rson]==-inf)) return query(lson,t-1,x,id); else { node ans=query(rson,t-1,x,id); ans.y+=(1<<(t-1)); return ans; } } else return query(lson,t-1,x,id); } }T; int main() { n=read(),m=read(); for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<=n;i++)f[i]=i; ll ans=0; for(int i=0;i<M-1;i++)T.lc[i]=T.rc[i]=0,T.maxv[i]=T.mixv[i]=-inf; int tot=0; while(true) { tot++; int cnt=0; for(int i=1;i<=n;i++)v[i]=0,f[i]=find(i); for(int i=1;i<=n;i++) { v[f[i]]=max(v[f[i]],i); if(i==f[i])cnt++; } for(int i=1;i<=n;i++)f[i]=v[f[i]]; if(cnt==1)break; for(int i=0;i<=T.size;i++)T.lc[i]=T.rc[i]=0,T.maxv[i]=T.mixv[i]=-inf; T.size=T.root=0; for(int i=1;i<=n;i++)T.insert(T.root,m,a[i],find(i)); T.solve(T.root,m); for(int i=1;i<=n;i++)w[i]=(node){-1,-1}; for(int x=1;x<=n;x++) { int id=find(x); node o=T.query(T.root,m,a[x],id); w[id]=max(w[id],o); } int tot=0; for(int i=1;i<=n;i++) if(w[i].x!=-1) { int x=w[i].x; if(find(i)!=find(w[x].x)||find(i)<find(w[i].x)) { ans+=w[i].y; p[++tot]=(node){find(i),find(w[i].x)}; } } for(int i=1;i<=tot;i++)merge(p[i].x,p[i].y); } printf("%lld",ans); return 0; }
uoj176 新年的繁榮