• 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 }
    代码在这里!
  • 相关阅读:
    机器学习1
    第15次作业
    算符优先分析
    自下而上语法分析
    实验二 递归下降语法分析
    LL(1)文法的判断,递归下降分析程序
    消除左递归
    【shell】通过shell编写ping包及arp的监控并发送短信
    os和sys模块
    time模块和random模块
  • 原文地址:https://www.cnblogs.com/wuliking/p/11272223.html
Copyright © 2020-2023  润新知