zoukankan      html  css  js  c++  java
  • 【BZOJ】【2819】NIM

    这题……咋说捏,其实是一道披着博弈论外衣的树上操作问题……

    随便用dfs序或者树链剖分转成序列,然后查询路径上的所有点的NIM和(异或和)就行了,毕竟除了是在树上以外,就是裸的NIM问题。

    树链剖分:一开始把线段树写跪了,然后输出“Yes”和“No”的时候全部大写了,再然后发现线段树空间开小了……

    代码如下:

      1 //BZOJ 2819
      2 #include<cstdio>
      3 #include<vector>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<iostream>
      7 #include<algorithm>
      8 #define rep(i,n) for(int i=0;i<n;++i)
      9 #define F(i,j,n) for(int i=j;i<=n;++i)
     10 #define D(i,j,n) for(int i=j;i>=n;--i)
     11 #define pb push_back
     12 using namespace std;
     13 const int N=500010;
     14 #define debug
     15 int n,a[N],t[N<<2],fa[N],top[N],dep[N],son[N],size[N],tid[N],cnt=0;
     16 vector<int>G[N];
     17 bool vis[N];
     18 
     19 #define mid (l+r>>1)
     20 #define L (o<<1)
     21 #define R (o<<1|1)
     22 void updata(int o,int l,int r,int pos,int v){
     23     if (l==r) t[o]=v;
     24     else{
     25         if (pos<=mid) updata(L,l,mid,pos,v);
     26         else updata(R,mid+1,r,pos,v);
     27         t[o]=t[L]^t[R];
     28     }
     29 }
     30 
     31 int ql,qr,ans=0;
     32 void query_it(int o,int l,int r){
     33     if (ql<=l && qr>=r) ans^=t[o];
     34     else{
     35         if (ql<=mid) query_it(L,l,mid);
     36         if (qr>mid) query_it(R,mid+1,r);
     37     }
     38 }
     39 //segment tree end
     40 
     41 void dfs(int x,int f,int deep){
     42     int y,maxsize=0;
     43     vis[x]=1; fa[x]=f; dep[x]=deep; size[x]=1; son[x]=0;
     44     rep(i,G[x].size()){
     45         y=G[x][i];
     46         if (vis[y]) continue;
     47         dfs(y,x,deep+1);
     48         size[x]+=size[y];
     49         if (size[y]>maxsize) maxsize=size[y],son[x]=y;
     50     }
     51 }
     52 
     53 void connect(int x,int f){
     54     tid[x]=++cnt;
     55     top[x]=f; vis[x]=1;
     56     if (son[x]) connect(son[x],f);
     57     rep(i,G[x].size()){
     58         int y=G[x][i];
     59         if (!vis[y]) connect(y,y);
     60     }
     61 }
     62 
     63 void query(int x,int y){
     64     while(top[x]!=top[y]){
     65         if (dep[top[x]]<dep[top[y]]) swap(x,y);
     66         ql=tid[top[x]]; qr=tid[x];
     67         query_it(1,1,n);
     68         x=fa[top[x]];
     69     }
     70     if (dep[x]>dep[y]) swap(x,y);
     71     ql=tid[x]; qr=tid[y];
     72     query_it(1,1,n);
     73 }
     74 
     75 int main(){
     76 //    freopen("file.in","r",stdin);
     77     scanf("%d",&n);
     78     F(i,1,n) scanf("%d",&a[i]);
     79     int x,y;
     80     F(i,2,n){
     81         scanf("%d%d",&x,&y);
     82         G[x].pb(y);
     83         G[y].pb(x);
     84     }
     85     dfs(1,0,1);
     86     memset(vis,0,sizeof vis);
     87     connect(1,1);
     88     F(i,1,n) updata(1,1,n,tid[i],a[i]);
     89     int q;
     90     scanf("%d",&q);
     91     char cmd[3];
     92     F(i,1,q){
     93         scanf("%s%d%d",cmd,&x,&y);
     94         if (cmd[0]=='Q'){
     95             ans=0;
     96             query(x,y);
     97             printf(ans ? "Yes
    " : "No
    ");
     98         }
     99         else updata(1,1,n,tid[x],y);
    100     }
    101     return 0;
    102 }
    View Code

    dfs序版:

    维护从根到x的异或和sum(x),则query(x,y)=sum(x)^sum(y)^a[lca(x,y)]

    自己画个图一眼就看出来了……公共部分两次异或互相抵消,但是LCA是在x-->y这条路径上的,所以要再加上

      1 /**************************************************************
      2     Problem: 2819
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:15004 ms
      7     Memory:65740 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 2819
     11 #include<cmath>
     12 #include<cstdio>
     13 #include<cstring>
     14 #include<cstdlib>
     15 #include<iostream>
     16 #include<algorithm>
     17 #define rep(i,n) for(int i=0;i<n;++i)
     18 #define F(i,j,n) for(int i=j;i<=n;++i)
     19 #define D(i,j,n) for(int i=j;i>=n;--i)
     20 using namespace std;
     21 void read(int &v){
     22     v=0; int sign=1; char ch=getchar();
     23     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     24     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
     25     v*=sign;
     26 }
     27 /******************tamplate*********************/
     28 const int N=500010;
     29 int head[N],to[N<<1],next[N<<1],cnt,fa[N];
     30 void add(int x,int y){
     31     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
     32     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
     33 }
     34 /*******************edge***********************/
     35 int n,m,dfs_clock,l[N],r[N],t[N<<1],a[N],deep[N];
     36 int st[N],top;
     37 void dfs(){
     38     st[++top]=1; fa[1]=0;deep[1]=1;
     39     while(top){
     40         int x=st[top];
     41         if (!l[x]){
     42             l[x]=++dfs_clock;
     43             for(int i=head[x];i;i=next[i])
     44                 if (to[i]!=fa[x]){
     45                     st[++top]=to[i];
     46                     fa[to[i]]=x;
     47                     deep[to[i]]=deep[x]+1;
     48                 }
     49         }
     50         else{
     51             r[x]=++dfs_clock;
     52             top--;
     53         }
     54     }
     55 }
     56 int p[N][20];
     57 void ST(){
     58     memset(p,-1,sizeof p);
     59     F(i,1,n) p[i][0]=fa[i];
     60     for(int j=1;(1<<j)<=n;++j)
     61         F(i,1,n)
     62             if (p[i][j-1]!=-1) p[i][j]=p[p[i][j-1]][j-1];
     63 }
     64 int lca(int x,int y){
     65     if (deep[x]<deep[y]) swap(x,y);
     66     int k=log(deep[x])/log(2);
     67     D(i,k,0)
     68         if (deep[x]-(1<<i)>=deep[y]) x=p[x][i];
     69     if (x==y) return y;
     70     D(i,k,0)
     71         if (p[x][i]!=-1 && p[x][i]!=p[y][i]){
     72             x=p[x][i]; y=p[y][i];
     73         }
     74     return p[x][0];
     75 }
     76 /*****************dfs&LCA***********************/
     77 inline int lowbit(int x){return x&(-x);}
     78 void update(int x,int val){
     79     for(x;x<=n*2;x+=lowbit(x)) t[x]^=val;
     80 }
     81 int sum(int x){
     82     int temp=0;
     83     for(x;x;x-=lowbit(x)) temp^=t[x];
     84     return temp;
     85 }
     86 /*********************fenwick*******************/
     87 int main(){
     88     read(n);
     89     F(i,1,n) read(a[i]);
     90     int x,y;
     91     F(i,2,n){
     92         read(x); read(y);
     93         add(x,y);
     94     }
     95     dfs();
     96     ST();
     97     F(i,1,n) update(l[i],a[i]),update(r[i],a[i]);
     98     read(m);
     99     char cmd[5];
    100     F(i,1,m){
    101         scanf("%s",cmd);
    102         read(x); read(y);
    103         if (cmd[0]=='Q') printf( sum(l[y])^sum(l[x])^a[lca(x,y)] ? "Yes
    " : "No
    ");
    104         else{
    105             update(l[x],a[x]); update(r[x],a[x]);
    106             update(l[x],y); update(r[x],y);
    107             a[x]=y;
    108         }
    109     }
    110     return 0;
    111 }
    View Code
  • 相关阅读:
    SQL语句基础之 单表查找
    SQL语句基础之 管理数据库,表 和 数据
    JavaWeb之 JSP:自定义标签
    JavaWeb之 JSP:内置对象,EL表达式,JSP标签基础
    JavaWeb之 JSP基础
    JavaWeb之Servlet:Cookie 和 Session
    JavaWeb之Servlet: ServletConfig 与 ServletContext
    JavaWeb之 Servlet执行过程 与 生命周期
    JavaWeb之Servlet:请求 与 响应
    Vue.js中 watch(深度监听)的最易懂的解释
  • 原文地址:https://www.cnblogs.com/Tunix/p/4201970.html
Copyright © 2011-2022 走看看