zoukankan      html  css  js  c++  java
  • BZOJ2819 Nim(DFS序)

    题目:单点修改、树链查询。

    可以直接用树链剖分做。。

    修改是O(QlogN),查询是O(QlogNlogN),Q=N=500000;

    听说会超时。。

    这题也可以用DFS序来做。

    先不看修改,单单查询:可以求出每个点到根的xor值,那么对任意两点的查询就等于xor(u)^xor(v)^val(lca(u,v));

    如果有修改:修改仅仅是单个点,而维护的只是点到根的路径,因此修改仅仅会影响到以这个点为根的子树的所有结点到根的信息。

    所以用DFS序把子树们化为连续区间用线段树维护,修改本质上是个线段树的区间修改,查询是个单点查询。

    每次修改和查询都是O(logN)。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 #define MAXN 550000
      6 struct Edge{
      7     int v,nxt;
      8 }edge[MAXN<<1];
      9 int NE,head[MAXN];
     10 void addEdge(int u,int v){
     11     edge[NE].v=v; edge[NE].nxt=head[u]; head[u]=NE++;
     12 }
     13 int n,stone[MAXN];
     14 int odr,stack[MAXN],l[MAXN],r[MAXN],dep[MAXN],fa[20][MAXN],val[MAXN];
     15 void dfs(){
     16     int top=0;
     17     stack[++top]=1;
     18     val[1]=stone[1];
     19     while(top){
     20         int u=stack[top];
     21         if(l[u]){
     22             r[u]=odr; --top;
     23             continue;
     24         }
     25         l[u]=++odr;
     26         for(int i=head[u]; i!=-1; i=edge[i].nxt){
     27             int v=edge[i].v;
     28             if(fa[0][u]==v) continue;
     29             fa[0][v]=u; dep[v]=dep[u]+1; val[v]=val[u]^stone[v]; stack[++top]=v;
     30         }
     31     }
     32 }
     33 
     34 int tree[MAXN<<2],N,x,y,z;
     35 void update(int i,int j,int k){
     36     if(x<=i && j<=y){
     37         tree[k]^=z;
     38         return;
     39     }
     40     if(tree[k]){
     41         tree[k<<1]^=tree[k]; tree[k<<1|1]^=tree[k];
     42         tree[k]=0;
     43     }
     44     int mid=i+j>>1;
     45     if(x<=mid) update(i,mid,k<<1);
     46     if(y>mid) update(mid+1,j,k<<1|1);
     47 }
     48 int query(int i,int j,int k){
     49     if(i==j) return tree[k];
     50     if(tree[k]){
     51         tree[k<<1]^=tree[k]; tree[k<<1|1]^=tree[k];
     52         tree[k]=0;
     53     }
     54     int mid=i+j>>1;
     55     if(x<=mid) return query(i,mid,k<<1);
     56     return query(mid+1,j,k<<1|1);
     57 }
     58 
     59 int lca(int u,int v){
     60     if(dep[u]>dep[v]) swap(u,v);
     61     for(int k=0; k<20; ++k){
     62         if((dep[v]-dep[u])>>k&1){
     63             v=fa[k][v];
     64         }
     65     }
     66     if(v==u) return u;
     67     for(int k=19; k>=0; --k){
     68         if(fa[k][u]!=fa[k][v]){
     69             u=fa[k][u];
     70             v=fa[k][v];
     71         }
     72     }
     73     return fa[0][u];
     74 }
     75 void init(){
     76     dfs();
     77     for(int i=1; i<20; ++i){
     78         for(int j=1; j<=n; ++j){
     79             int t=fa[i-1][j];
     80             if(t) fa[i][j]=fa[i-1][t];
     81         }
     82     }
     83     for(N=1; N<odr; N<<=1);
     84     for(int i=1; i<=n; ++i){
     85         x=l[i]; y=l[i]; z=val[i];
     86         update(1,N,1);
     87     }
     88 }
     89 int main(){
     90     int q,a,b;
     91     char op[11];
     92     memset(head,-1,sizeof(head));
     93     scanf("%d",&n);
     94     for(int i=1; i<=n; ++i){
     95         scanf("%d",stone+i);
     96     }
     97     for(int i=1; i<n; ++i){
     98         scanf("%d%d",&a,&b);
     99         addEdge(a,b);
    100         addEdge(b,a);
    101     }
    102     init();
    103     scanf("%d",&q);
    104     while(q--){
    105         scanf("%s%d%d",op,&a,&b);
    106         if(op[0]=='Q'){
    107             int res;
    108             x=l[a]; res=query(1,N,1);
    109             x=l[b]; res^=query(1,N,1);
    110             res^=stone[lca(a,b)];
    111             if(res) puts("Yes");
    112             else puts("No");
    113         }else{
    114             x=l[a]; y=r[a]; z=b^stone[a];
    115             update(1,N,1);
    116             stone[a]=b;
    117         }
    118     }
    119     return 0;
    120 }
  • 相关阅读:
    第13章 使用ADO.NET访问数据库
    第11章 连接查询和分组查询
    第10章 模糊查询和聚合函数
    第9章 数据查询基础
    数据库前三章测试题
    用表组织数据
    程序数据集散地:数据库
    深入C#的String类
    线程池
    hadoop-2.8.0 完全分布式运行模式
  • 原文地址:https://www.cnblogs.com/WABoss/p/4886918.html
Copyright © 2011-2022 走看看