CF888G Xor-MST[最小生成树+01trie]

前注:关于这题,本人的解法暂时没有成功通过此题,原因是被卡常了。可能需要等待某种机缘来请人调试。


类似uoj的一道题(新年的繁荣),不过是一个有些简单的版本。

因为是完全图,有没有办法明显优化建边,所以考虑用这个Boruvka算法。MST学习笔记里应当记下来了,可以自行前往。然后在这里,就发现使用Boruvka的话明显就有了可以优化的地方——每个点向外找一条最小的边。这里,因为异或的特殊性,所以可以想到用01trie来查找xor最小值。于是boruvka就与数据结构结合起来了。然后照着流程做即可。

不过注意一个问题:每轮连通块内的点找trie上最小异或值,可能会找到块内的点(甚至自己),所以要避免,这里可以对于每个子树,维护一个min,max,代表子树内叶子代表的点所在的块编号的最大最小值,于是查找的时候就可以提前判断,避免走入不合法的地方。

但是被卡常了。。2s时限,跑了2.6左右。。难受。。等待救援。咕咕。

  1 #pragma comment(linker,"/STACK:102400000,102400000")
  2 #pragma GCC optimize("Ofast")
  3 #pragma GCC optimize("inline")
  4 #pragma GCC optimize("-fgcse")
  5 #pragma GCC optimize("-fgcse-lm")
  6 #pragma GCC optimize("-fipa-sra")
  7 #pragma GCC optimize("-ftree-pre")
  8 #pragma GCC optimize("-ftree-vrp")
  9 #pragma GCC optimize("-fpeephole2")
 10 #pragma GCC optimize("-ffast-math")
 11 #pragma GCC optimize("-fsched-spec")
 12 #pragma GCC optimize("unroll-loops")
 13 #pragma GCC optimize("-falign-jumps")
 14 #pragma GCC optimize("-falign-loops")
 15 #pragma GCC optimize("-falign-labels")
 16 #pragma GCC optimize("-fdevirtualize")
 17 #pragma GCC optimize("-fcaller-saves")
 18 #pragma GCC optimize("-fcrossjumping")
 19 #pragma GCC optimize("-fthread-jumps")
 20 #pragma GCC optimize("-funroll-loops")
 21 #pragma GCC optimize("-fwhole-program")
 22 #pragma GCC optimize("-freorder-blocks")
 23 #pragma GCC optimize("-fschedule-insns")
 24 #pragma GCC optimize("inline-functions")
 25 #pragma GCC optimize("-ftree-tail-merge")
 26 #pragma GCC optimize("-fschedule-insns2")
 27 #pragma GCC optimize("-fstrict-aliasing")
 28 #pragma GCC optimize("-fstrict-overflow")
 29 #pragma GCC optimize("-falign-functions")
 30 #pragma GCC optimize("-fcse-skip-blocks")
 31 #pragma GCC optimize("-fcse-follow-jumps")
 32 #pragma GCC optimize("-fsched-interblock")
 33 #pragma GCC optimize("-fpartial-inlining")
 34 #pragma GCC optimize("no-stack-protector")
 35 #pragma GCC optimize("-freorder-functions")
 36 #pragma GCC optimize("-findirect-inlining")
 37 #pragma GCC optimize("-fhoist-adjacent-loads")
 38 #pragma GCC optimize("-frerun-cse-after-loop")
 39 #pragma GCC optimize("inline-small-functions")
 40 #pragma GCC optimize("-finline-small-functions")
 41 #pragma GCC optimize("-ftree-switch-conversion")
 42 #pragma GCC optimize("-foptimize-sibling-calls")
 43 #pragma GCC optimize("-fexpensive-optimizations")
 44 #pragma GCC optimize("-funsafe-loop-optimizations")
 45 #pragma GCC optimize("inline-functions-called-once")
 46 #pragma GCC optimize("-fdelete-null-pointer-checks")
 47 #include<iostream>
 48 #include<cstdio>
 49 #include<cstring>
 50 #include<algorithm>
 51 #include<cmath>
 52 #include<queue>
 53 #define dbg(x) cerr << #x << " = " << x <<endl
 54 #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
 55 using namespace std;
 56 typedef long long ll;
 57 typedef double db;
 58 typedef pair<int,int> pii;
 59 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
 60 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
 61 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
 62 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
 63 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
 64 template<typename T>inline T read(T&x){
 65     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
 66     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
 67 }
 68 const int N=2e5+5,INF=0x3f3f3f3f;
 69 int len,n,thxorz;
 70 int A[N];
 71 int anc[N];
 72 inline int get_anc(int x){return anc[x]==x?x:anc[x]=get_anc(anc[x]);}
 73 struct _01trie{
 74     int tr[N*30][2],maxv[N*30],minv[N*30],id[N*30],tot;
 75     _01trie(){maxv[0]=0,minv[0]=INF;}
 76     inline void Insert(int x,int j){//dbg2(x,j);
 77         int u=0;
 78         for(register int i=len,d;~i;--i){
 79             if(!tr[u][d=(x>>i)&1])tr[u][d]=++tot;
 80             u=tr[u][d];
 81         }
 82         id[u]=j;
 83     }
 84     void Maintain(int i){//++thxorz;
 85         if(!tr[i][0]&&!tr[i][1]){maxv[i]=minv[i]=get_anc(id[i]);return;}
 86         if(tr[i][0])Maintain(tr[i][0]);
 87         if(tr[i][1])Maintain(tr[i][1]);
 88         maxv[i]=_max(maxv[tr[i][0]],maxv[tr[i][1]]);
 89         minv[i]=_min(minv[tr[i][0]],minv[tr[i][1]]);//dbg2(i,tr[i][0]),dbg2(minv[i],maxv[i]);
 90     }
 91     inline void Build(){for(register int i=1;i<=n;++i)Insert(A[i],i);}
 92     inline int Query(int x,int j){
 93         int u=0,rt=get_anc(j);//dbg2(rt,x);
 94         for(register int i=len,d;~i;--i){//++thxorz;
 95             d=(x>>i)&1;//dbg2(d,tr[u][d]),dbg2(maxv[tr[u][d]],minv[tr[u][d]]);
 96             if(tr[u][d]&&(maxv[tr[u][d]]^rt||minv[tr[u][d]]^rt))u=tr[u][d];
 97             else u=tr[u][d^1];
 98         }//dbg(id[u]);
 99         return id[u];
100     }
101 }T;
102 int minw[N],minp[N];
103 inline void Boruvka(){
104     int k=0;ll ans=0;
105     T.Build();
106     for(register int i=1;i<=n;++i)anc[i]=i;
107     while(k<n-1){//dbg("new round");
108         T.maxv[0]=0,T.minv[0]=INF,T.Maintain(0);memset(minw,0x7f,sizeof minw);
109         for(register int i=1,tmp;i<=n;++i)tmp=T.Query(A[i],i),MIN(minw[get_anc(i)],A[tmp]^A[i])&&(minp[anc[i]]=tmp);
110         for(register int i=1;i<=n;++i)if(get_anc(i)^get_anc(minp[get_anc(i)]))
111             ans+=minw[anc[i]],++k,anc[anc[i]]=anc[minp[anc[i]]];//attention the order.
112     }
113     printf("%I64d
",ans);
114 }
115 
116 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
117     read(n);for(register int i=1;i<=n;++i)MAX(len,read(A[i]));
118     len=__lg(len);
119     Boruvka();//dbg(thxorz);
120     return 0;
121 }
View Code

原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11674419.html