zoukankan      html  css  js  c++  java
  • 【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)

    4568: [Scoi2016]幸运数字

    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

    【分析】

      看看时限就知道怎么做了。。

      线段树维护区间的线性基。

      区间合并线性基,就一个个元素插进去就可以了。【操作带一个常数60

      树的话就剖一下。

      然后用线性基的性质求异或和的最大值,就是从高位开始枚举,若^所得比ans大就把它异或进去。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 #define Maxn 20010
      8 #define LL long long
      9 
     10 LL a[Maxn],aa[Maxn];
     11 
     12 struct nnode
     13 {
     14     int x,y,next;
     15 }t[Maxn*2];
     16 int len,first[Maxn];
     17 
     18 void ins(int x,int y)
     19 {
     20     t[++len].x=x;t[len].y=y;
     21     t[len].next=first[x];first[x]=len;
     22 }
     23 
     24 int fa[Maxn],son[Maxn],sm[Maxn],dep[Maxn];
     25 void dfs1(int x,int ff)
     26 {
     27     son[x]=0;fa[x]=ff;sm[x]=1;
     28     dep[x]=dep[ff]+1;
     29     for(int i=first[x];i;i=t[i].next) if(t[i].y!=ff)
     30     {
     31         int y=t[i].y;
     32         dfs1(y,x);
     33         sm[x]+=sm[y];
     34         if(son[x]==0||sm[y]>sm[son[x]]) son[x]=y;
     35     }
     36 }
     37 
     38 int dfn[Maxn],tp[Maxn],cnt;
     39 void dfs2(int x,int tpp)
     40 {
     41     tp[x]=tpp;dfn[x]=++cnt;
     42     aa[cnt]=a[x];
     43     if(son[x]) dfs2(son[x],tpp);
     44     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x])
     45     {
     46         int y=t[i].y;
     47         dfs2(y,y);
     48     }
     49 }
     50 
     51 struct node
     52 {
     53     int l,r,lc,rc;
     54     LL w[61];
     55 }tr[Maxn*2];
     56 
     57 void ist(int x,LL y)
     58 {
     59     for(int i=60;i>=0;i--) if((1LL<<i)&y)
     60     {
     61         if(tr[x].w[i]) y^=tr[x].w[i];
     62         else {tr[x].w[i]=y;break;}
     63     }
     64 }
     65 
     66 void merge(int x,int y)
     67 {
     68     for(int i=0;i<=60;i++) if(tr[y].w[i]!=0) ist(x,tr[y].w[i]);
     69 }
     70 
     71 int tot;
     72 int build(int l,int r)
     73 {
     74     int x=++tot;
     75     tr[x].l=l;tr[x].r=r;
     76     memset(tr[x].w,0,sizeof(tr[x].w));
     77     if(l!=r)
     78     {
     79         int mid=(l+r)>>1;
     80         tr[x].lc=build(l,mid);
     81         tr[x].rc=build(mid+1,r);
     82         merge(x,tr[x].lc);
     83         merge(x,tr[x].rc);
     84     }
     85     else
     86     {
     87         tr[x].lc=tr[x].rc=0;
     88         ist(x,aa[l]);
     89     }
     90     return x;
     91 }
     92 
     93 void query(int x,int l,int r)
     94 {
     95     if(tr[x].l==l&&tr[x].r==r)
     96     {
     97         merge(0,x);
     98         return;
     99     }
    100     int mid=(tr[x].l+tr[x].r)>>1;
    101     if(r<=mid) query(tr[x].lc,l,r);
    102     else if(l>mid) query(tr[x].rc,l,r);
    103     else
    104     {
    105         query(tr[x].lc,l,mid);
    106         query(tr[x].rc,mid+1,r);
    107     }
    108 }
    109 
    110 LL fquery(int x,int y)
    111 {
    112     memset(tr[0].w,0,sizeof(tr[0].w));
    113     while(tp[x]!=tp[y])
    114     {
    115         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
    116         query(1,dfn[tp[x]],dfn[x]);
    117         x=fa[tp[x]];
    118     }
    119     if(dep[x]<dep[y]) swap(x,y);
    120     query(1,dfn[y],dfn[x]);
    121     LL ans=0;
    122     for(int i=60;i>=0;i--) if((ans^tr[0].w[i])>ans) ans^=tr[0].w[i];
    123     return ans;
    124 }
    125 
    126 int main()
    127 {
    128     int n,q;
    129     scanf("%d%d",&n,&q);
    130     len=0;
    131     memset(first,0,sizeof(first));
    132     for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    133     for(int i=1;i<n;i++)
    134     {
    135         int x,y;
    136         scanf("%d%d",&x,&y);
    137         ins(x,y);ins(y,x);
    138     }
    139     dep[0]=0;
    140     dfs1(1,0);cnt=0;
    141     dfs2(1,1);tot=0;
    142     build(1,n);
    143     for(int i=1;i<=q;i++)
    144     {
    145         int x,y;
    146         scanf("%d%d",&x,&y);
    147         printf("%lld
    ",fquery(x,y));
    148     }
    149     return 0;
    150 }
    View Code

    2017-03-13 14:06:24

  • 相关阅读:
    Unity The Method Signature Matching Rule
    Unity The Property Matching Rule
    Unity The Type Matching Rule
    Unity The Custom Attribute Matching Rule
    Unity The Member Name Matching Rule
    Unity No Policies
    Unity The Return Type Matching Rule
    Unity The Parameter Type Matching Rule
    Unity The Namespace Matching Rule
    关于TSQL递归查询的(转)
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6542534.html
Copyright © 2011-2022 走看看