zoukankan      html  css  js  c++  java
  • NewTrain1 T7: Nim

    题目分析

    关于Nim游戏,当所有堆异或起来为0时,必输,否则有必胜方法。

    所以,问题就转化成了在线询问树上一条道路上点权的异或值并支持修改。

    在树上的询问不好搞,所以我们使用bfs序将原树转化成一段区间。

    对于一次查询,也就转化成了一段区间的异或和。

    考虑一个点会影响哪个区间,已知,就是访问到它的时刻到遍历完它的所有子树之后再回来的那个时刻。

    所以,我们记录一个点初次访问和离开的bfs序,在树状数组上查询即可。(查询时因为树状数组维护的是他到根的异或和,这时两点的Lca被异或掉了,所以要再异或一下Lca的值)

    那么怎么处理修改呢?

    因为是异或,所以对于一个点,再更新一遍它就等于把这个点删掉。所以我们用原值更新一下这个点,再用新的值更新就行了。

      1 #include<bits/stdc++.h>
      2 #define INTMAX 2147483647LL
      3 #define PII pair<int,int>
      4 #define MK make_pair
      5 #define re register
      6 using namespace std;
      7 typedef long long ll;
      8 const double Pi=acos(-1.0);
      9 const int Inf=0x3f3f3f3f;
     10 const int MAXN=5e5+10; 
     11 inline int read(){
     12     re int x=0,f=1,ch=getchar();
     13     while(!isdigit(ch))f=ch=='-'?-1:1,ch=getchar();
     14     while(isdigit(ch))x=x*10+ch-48,ch=getchar();
     15     return x*f;
     16 }
     17 inline ll readll(){
     18     re ll x=0,f=1,ch=getchar();
     19     while(!isdigit(ch))f=ch=='-'?-1:1,ch=getchar();
     20     while(isdigit(ch))x=x*10+ch-48,ch=getchar();
     21     return x*f;
     22 }
     23 
     24 struct Edge{
     25     int to,nxt;
     26 }e[MAXN<<1];
     27 int cnt,head[MAXN];
     28 inline void add_edge(int u,int v){
     29     e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
     30 }
     31 int n,m;
     32 int bse[25],BIT[MAXN];
     33 int a[MAXN];
     34 int tim,l[MAXN],r[MAXN];
     35 int dep[MAXN],fa[MAXN][25];
     36 char ch[5];
     37 inline void dfs(int x){
     38     for(int i=1;i<=20;++i)
     39         if(dep[x]>=bse[i])
     40             fa[x][i]=fa[fa[x][i-1]][i-1];
     41         else
     42             break;
     43     l[x]=++tim;
     44     for(int i=head[x],y;i;i=e[i].nxt){
     45         y=e[i].to;
     46         if(y!=fa[x][0]){
     47             dep[y]=dep[x]+1;fa[y][0]=x;
     48             dfs(y);
     49         }
     50     }
     51     r[x]=tim;
     52 }
     53 inline int lowbit(int x){return x&(-x);}
     54 inline void Update(int x,int v){for(int i=x;i<=n;i+=lowbit(i)) BIT[i]^=v;}
     55 inline int Query(int x){int res=0;for(int i=x;i;i-=lowbit(i))res^=BIT[i];return res;}
     56 inline int Get_lca(int x,int y){
     57     if(dep[x]<dep[y]) swap(x,y);
     58     int tmp=dep[x]-dep[y];
     59     for(int i=0;i<=20;++i)
     60         if(bse[i]&tmp)
     61             x=fa[x][i];
     62     for(int i=20;i>=0;--i)
     63         if(fa[x][i]!=fa[y][i])
     64             x=fa[x][i],y=fa[y][i];
     65     if(x==y) return x;
     66     return fa[x][0];
     67 }
     68 int main(){
     69     bse[0]=1;for(int i=1;i<=21;++i) bse[i]=bse[i-1]<<1;
     70     n=read();
     71     for(int i=1;i<=n;++i) a[i]=read();
     72     for(int i=1,u,v;i<n;++i){
     73         u=read();v=read();
     74         add_edge(u,v);
     75         add_edge(v,u);
     76     }
     77     dfs(1);
     78     //cout<<111<<endl;
     79     for(int i=1;i<=n;++i){
     80         Update(l[i],a[i]);
     81         Update(r[i]+1,a[i]);
     82     }
     83     //cout<<2<<endl;
     84     m=read();
     85     while(m--){
     86         scanf("%s",ch);
     87         int x=read(),y=read();
     88         if(ch[0]=='Q'){
     89             int lca=Get_lca(x,y);
     90             int res=Query(l[x])^Query(l[y])^a[lca];
     91             puts(res?"Yes":"No");
     92         }
     93         else{
     94             Update(l[x],a[x]);Update(r[x]+1,a[x]);
     95             a[x]=y;
     96             Update(l[x],a[x]);Update(r[x]+1,a[x]);
     97         }
     98     } 
     99     return 0;
    100 } 
  • 相关阅读:
    ORACLE 查找数据库中有记录的表
    [原]Asp.Net 错误:无法连接到Asp.Net Developement server
    中国移动手机话费查询号码1008611
    动手修改VS2008的解决方案文件,以让VS2005打开它
    [转]飞秋使用说明与常见问题解决方法
    微软发布Fix it 修复Windows 7等系统0day漏洞
    Oracle DECODE 函数应用示例
    [转]C#实现访问网络共享文件夹
    c#保留小数点后位数的方法
    [转]微软紧急修复高危漏洞 30万网民PC已遭攻击
  • 原文地址:https://www.cnblogs.com/LI-dox/p/11267234.html
Copyright © 2011-2022 走看看