• Bzoj4568 [Scoi2016]幸运数字


    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 863  Solved: 342

    Description

    A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一。每座城市都有一个
    幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征。一些旅行者希望游览 A 国。旅行者计划
    乘飞机降落在 x 号城市,沿着 x 号城市到 y 号城市之间那条唯一的路径游览,最终从 y 城市起飞离开 A 国。
    在经过每一座城市时,游览者就会有机会与这座城市的幸运数字拍照,从而将这份幸运保存到自己身上。然而,幸
    运是不能简单叠加的,这一点游览者也十分清楚。他们迷信着幸运数字是以异或的方式保留在自己身上的。例如,
    游览者拍了 3 张照片,幸运值分别是 5,7,11,那么最终保留在自己身上的幸运值就是 9(5 xor 7 xor 11)。
    有些聪明的游览者发现,只要选择性地进行拍照,便能获得更大的幸运值。例如在上述三个幸运值中,只选择 5 
    和 11 ,可以保留的幸运值为 14 。现在,一些游览者找到了聪明的你,希望你帮他们计算出在他们的行程安排中
    可以保留的最大幸运值是多少。
     

    Input

    第一行包含 2 个正整数 n ,q,分别表示城市的数量和旅行者数量。第二行包含 n 个非负整数,其中第 i 个整
    数 Gi 表示 i 号城市的幸运值。随后 n-1 行,每行包含两个正整数 x ,y,表示 x 号城市和 y 号城市之间有一
    条道路相连。随后 q 行,每行包含两个正整数 x ,y,表示这名旅行者的旅行计划是从 x 号城市到 y 号城市。N
    <=20000,Q<=200000,Gi<=2^60
     

    Output

     输出需要包含 q 行,每行包含 1 个非负整数,表示这名旅行者可以保留的最大幸运值。

     

    Sample Input

    4 2
    11 5 7 9
    1 2
    1 3
    1 4
    2 3
    1 4

    Sample Output

    14
    11

    HINT

     

    Source

    树链剖分+线性基

    维护每个结点的线性基,查询的时候就用树剖合并路径上的线性基

    树剖都快写完了才想起来LCA,悲伤。

    然后开始漫长的调试,无限RE之后,发现树剖上溯时候的深度比较写反了。

    絶望だ——

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<queue>
      6 #define LL long long
      7 using namespace std;
      8 const int mxn=20010;
      9 int read(){
     10     int x=0,f=1;char ch=getchar();
     11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     12     while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
     13     return x*f;
     14 }
     15 LL read1(){
     16     LL x=0,f=1;char ch=getchar();
     17     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     18     while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
     19     return x*f;
     20 }
     21 struct edge{
     22     int v,nxt;
     23 }e[mxn<<1];
     24 int hd[mxn],mct=0;
     25 void add_edge(int u,int v){e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;}
     26 struct node{
     27     int w,e,top;
     28     int fa,son,size;
     29 }t[mxn];
     30 LL a[mxn];
     31 int dep[mxn],id[mxn],sz=0;
     32 void DFS1(int u,int fa){
     33     t[u].size=1;
     34     dep[u]=dep[fa]+1;
     35     for(int i=hd[u];i;i=e[i].nxt){
     36         int v=e[i].v;
     37         if(v==fa)continue;
     38         t[v].fa=u;
     39         DFS1(v,u);
     40         t[u].size+=t[v].size;
     41         if(t[v].size>t[t[u].son].size)
     42             t[u].son=v;
     43     }
     44     return;
     45 }
     46 void DFS2(int u,int top){
     47     t[u].w=++sz;t[u].top=top;
     48     id[sz]=u;
     49     if(t[u].son){DFS2(t[u].son,top);}   
     50     for(int i=hd[u];i;i=e[i].nxt){
     51         int v=e[i].v;
     52         if(v==t[u].fa || v==t[u].son)continue;
     53         DFS2(v,v);
     54     }
     55     t[u].e=sz;
     56     return;
     57 }
     58 //
     59 int n,q;
     60 struct SGT{
     61     LL a[63];
     62 }st[mxn<<2];
     63 void merge(LL *a,LL *b,LL *c){//合并线性基 
     64     for(int i=0;i<=62;i++)a[i]=b[i];
     65     for(int i=62;i>=0;i--)
     66         if(c[i]){
     67             LL tmp=c[i];
     68             for(int j=62;j>=0;j--)
     69                 if((tmp>>j)&1){
     70                     if(!a[j]){a[j]=tmp;break;}
     71                     tmp^=a[j];
     72                 }
     73     }
     74     return;
     75 }
     76 void Build(int l,int r,int rt){
     77     if(l==r){
     78         memset(st[rt].a,0,sizeof st[rt].a);
     79         LL res=a[id[l]];
     80         for(int i=62;i>=0;i--)
     81             if((res>>i)&1){
     82                 if(!st[rt].a[i]){st[rt].a[i]=res;break;}
     83                 else res^=st[rt].a[i];
     84             }
     85         return;
     86     }
     87     int mid=(l+r)>>1;
     88     Build(l,mid,rt<<1);Build(mid+1,r,rt<<1|1);
     89     merge(st[rt].a,st[rt<<1].a,st[rt<<1|1].a);
     90     return;
     91 }
     92 LL ans[64];
     93 void query(int L,int R,int l,int r,int rt){
     94 //  printf("L:%d R:%d l:%d r:%d rt:%d
    ",L,R,l,r,rt);
     95     if(L<=l && r<=R){
     96         merge(ans,ans,st[rt].a);return;
     97     }
     98     int mid=(l+r)>>1;
     99     if(L<=mid)query(L,R,l,mid,rt<<1);
    100     if(R>mid)query(L,R,mid+1,r,rt<<1|1);
    101     return;
    102 }
    103 void Que(int x,int y){
    104     while(t[x].top!=t[y].top){
    105         if(dep[t[x].top]<dep[t[y].top])swap(x,y);
    106 //      printf("x:%d y:%d x.top:%d
    ",x,y,t[x].top);
    107         query(t[t[x].top].w,t[x].w,1,n,1);
    108         x=t[t[x].top].fa;
    109     }
    110     if(dep[x]>dep[y])swap(x,y);
    111     query(t[x].w,t[y].w,1,n,1);
    112     return;
    113 }
    114 //
    115 int main(){
    116     int i,j,u,v;
    117     n=read();q=read();
    118     for(i=1;i<=n;i++)a[i]=read1();
    119     for(i=1;i<n;i++){
    120         u=read();v=read();
    121         add_edge(u,v);add_edge(v,u);
    122     }
    123     DFS1(1,0);
    124     DFS2(1,1);
    125     Build(1,n,1);
    126     while(q--){
    127         u=read();v=read();
    128         memset(ans,0,sizeof ans);
    129         Que(u,v);
    130         LL tmp=0;
    131         for(i=62;i>=0;i--)tmp=max(tmp,tmp^ans[i]);
    132         printf("%lld
    ",tmp);
    133     }
    134     return 0;
    135 }
  • 相关阅读:
    【单调队列】POJ2823-Sliding Window
    【单调队列】广告印刷
    反射复习笔记01
    redis 笔记01 简单动态字符串、链表、字典、跳跃表、整数集合、压缩列表
    mybatis 复习笔记02
    mybatis 复习笔记01
    Mongodb 笔记02 创建、更新和删除文档
    NIO复习03
    Mongodb 笔记01 MongoDB 简介、MongoDB基础知识、启动和停止MongoDB
    NIO复习02
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6360324.html
Copyright © 2020-2023  润新知