P3292 [SCOI2016]幸运数字(倍增LCA+线性基)

题目链接:https://www.luogu.org/problem/P3292

解题报告:看到异或和最大,首先想到线性基,然而是在树上的,就考虑倍增LCA然后暴力插入线性基!

AC代码:

  1 #include<vector>
  2 #include<cstdio>
  3 #include<iostream>
  4 #include<cmath>
  5 #include<queue>
  6 #include<stack>
  7 #include<cmath>
  8 #include<algorithm>
  9 #define numm ch-48
 10 #define pd putchar(' ')
 11 #define pn putchar('
')
 12 #define pb push_back
 13 #define fi first
 14 #define se second
 15 #define fre1 freopen("1.txt","r",stdin)
 16 #define fre2 freopen("2.txt","w",stdout)
 17 using namespace std;
 18 template <typename T>
 19 void read(T &res) {
 20     bool flag=false;char ch;
 21     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
 22     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
 23     flag&&(res=-res);
 24 }
 25 template <typename T>
 26 void write(T x) {
 27     if(x<0) putchar('-'),x=-x;
 28     if(x>9) write(x/10);
 29     putchar(x%10+'0');
 30 }
 31 const int maxn=20010;
 32 const int N=60;
 33 const int inf=0x3f3f3f3f;
 34 const int INF=0x7fffffff;
 35 const int LOG=18;
 36 typedef long long ll;
 37 struct edge {
 38     int v,net;
 39 }e[maxn<<1];
 40 int cnt=0,head[maxn];
 41 void add(int u,int v) {
 42     e[++cnt].v=v;
 43     e[cnt].net=head[u];
 44     head[u]=cnt;
 45 }
 46 struct wtz {
 47     ll p[65];
 48     void clean() { for(int i=0;i<=61;i++) p[i]=0; }
 49     void add(ll x) {
 50         for(int i=61;~i;i--)
 51             if(x&(1LL<<i))
 52                 if(!p[i]){
 53                     p[i]=x;
 54                     break;
 55                 }
 56                 else x^=p[i];
 57     }
 58 }g[maxn][20],ans;
 59 int depth[maxn],f[maxn][20];
 60 void merges(wtz &x,wtz y) { ///合并线性基
 61     for(int i=61;~i;i--)
 62         if(y.p[i]) x.add(y.p[i]);
 63 }
 64 void dfs(int u,int fath) {
 65     depth[u]=depth[fath]+1;
 66     f[u][0]=fath;
 67     for(int i=1;i<=LOG;i++) {
 68         f[u][i]=f[f[u][i-1]][i-1];
 69         g[u][i]=g[u][i-1];  ///g[u][i]由g[u][i-1]和g[f[u][i-1]][i-1]两块组成
 70         merges(g[u][i],g[f[u][i-1]][i-1]);
 71     }
 72     for(int i=head[u];~i;i=e[i].net){
 73 
 74         if(e[i].v!=fath) dfs(e[i].v,u);
 75 
 76     }
 77 }
 78 void lca(int x,int y) {
 79     if(depth[x]<depth[y]) swap(x,y);
 80     for(int i=LOG;~i;i--)
 81         if(depth[f[x][i]]>=depth[y]) {
 82             merges(ans,g[x][i]),x=f[x][i];
 83         }
 84     if(x==y) {
 85         merges(ans,g[x][0]);
 86         return ;
 87     }
 88     for(int i=LOG;~i;i--) {
 89         if(f[x][i]!=f[y][i]) {
 90             merges(ans,g[x][i]);
 91             merges(ans,g[y][i]);
 92             x=f[x][i];
 93             y=f[y][i];
 94         }
 95     }
 96     merges(ans,g[x][0]);
 97     merges(ans,g[y][0]);
 98     merges(ans,g[f[x][0]][0]);
 99 }
100 int main()
101 {
102     int n,q,a,b;
103     read(n),read(q);
104     for(int i=1;i<=n;i++)
105         head[i]=-1;
106     ll x;
107     for(int i=1;i<=n;i++) {
108         read(x);
109         g[i][0].add(x);
110     }
111     for(int i=1;i<=n-1;i++) {
112         read(a),read(b);
113         add(a,b);
114         add(b,a);
115     }
116     dfs(1,0);
117     for(int i=1;i<=q;i++) {
118         ans.clean();
119         ll res=0;
120         read(a),read(b);
121         lca(a,b);
122         for(int j=61;~j;j--)
123             if((ans.p[j]^res)>res) res^=ans.p[j];
124         write(res);pn;
125     }
126     return 0;
127 }
代码在这里!
原文地址:https://www.cnblogs.com/wuliking/p/11272223.html