zoukankan      html  css  js  c++  java
  • bzoj2819: Nim(博弈+树剖)

    2819: Nim

    题目:传送门 


    题解:

       很久之前学博弈的时候看过的一道水题,其实算不上博弈吧...

       直接套上一个裸的树剖啊,把路径上的点值全都xor(xor满足结合率所以就不管那么多随便搞啦)

       dog B 肉老师,竟然不告诉我它卡常,搞得我TLE几百年

        


    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<iostream>
      7 using namespace std;
      8 inline int read()
      9 {
     10     int f=1,x=0;char ch;
     11     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     12     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     13     return f*x;
     14 }
     15 struct node
     16 {
     17     int x,y,next;
     18 }a[1110000];int len,last[510000];
     19 inline void ins(int x,int y)
     20 {
     21     len++;a[len].x=x;a[len].y=y;
     22     a[len].next=last[x];last[x]=len;
     23 }
     24 struct trnode
     25 {
     26     int l,r,c,lc,rc;
     27 }tr[1110000];int trlen;
     28 inline void bt(int l,int r)
     29 {
     30     int now=++trlen;
     31     tr[now].l=l;tr[now].r=r;tr[now].c=0;
     32     tr[now].lc=tr[now].rc=-1;
     33     if(l<r)
     34     {
     35         int mid=(tr[now].l+tr[now].r)/2;
     36         tr[now].lc=trlen+1;bt(l,mid);
     37         tr[now].rc=trlen+1;bt(mid+1,r);
     38     }
     39 }
     40 inline void change(int now,int p,int c)
     41 {
     42     if(tr[now].l==tr[now].r){tr[now].c=c;return ;}
     43     int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
     44     if(p<=mid)change(lc,p,c);
     45     else change(rc,p,c);
     46     tr[now].c=tr[lc].c^tr[rc].c;
     47 }
     48 inline int getsum(int now,int l,int r)
     49 {
     50     if(tr[now].l==l && r==tr[now].r)return tr[now].c;
     51     int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
     52     if(r<=mid)return getsum(lc,l,r);
     53     else if(mid+1<=l)return getsum(rc,l,r);
     54     return getsum(lc,l,mid)^getsum(rc,mid+1,r);
     55 }
     56 int n,fa[510000],son[510000],dep[510000],tot[510000];
     57 inline void pre_tree_node(int x)
     58 {
     59     son[x]=0;tot[x]=1;
     60     for(register int k=last[x];k;k=a[k].next)
     61     {
     62         int y=a[k].y;
     63         if(y!=fa[x])
     64         {
     65             dep[y]=dep[x]+1;
     66             fa[y]=x;
     67             pre_tree_node(y);
     68             if(tot[y]>tot[son[x]])son[x]=y;
     69             tot[x]+=tot[y];
     70         }
     71     }
     72 }
     73 int top[510000],ys[510000],id,tp;
     74 inline void pre_tree_edge(int x)
     75 {
     76     int tt=tp;top[x]=tp;ys[x]=++id;
     77     if(son[x]!=0)pre_tree_edge(son[x]);
     78     for(register int k=last[x];k;k=a[k].next)
     79     {
     80         int y=a[k].y;
     81         if(y!=son[x] && y!=fa[x])
     82         {
     83             tp=y;
     84             pre_tree_edge(y);
     85             tp=tt;
     86         }
     87     }
     88 }
     89 int sol(int x,int y)
     90 {
     91     int ans=0,tx=top[x],ty=top[y];
     92     while(tx!=ty)
     93     {
     94         if(dep[tx]>dep[ty])swap(tx,ty),swap(x,y);
     95         ans^=getsum(1,ys[ty],ys[y]);
     96         y=fa[ty];ty=top[y];
     97     }
     98     if(x==y)return ans^getsum(1,ys[x],ys[x]);
     99     else
    100     {
    101         if(dep[x]>dep[y])swap(x,y);
    102         return ans^getsum(1,ys[x],ys[y]);
    103     }
    104 }
    105 int st[510000],Q;
    106 char s[3];
    107 int main()
    108 {
    109     //freopen("a.in","r",stdin);freopen("a.out","w",stdout);
    110     n=read();for(int i=1;i<=n;++i)st[i]=read();
    111     len=0;memset(last,0,sizeof(last));
    112     for(register int i=1;i<n;++i)
    113     {
    114         int x=read(),y=read();
    115         ins(x,y);ins(y,x);
    116     }
    117     fa[1]=0;dep[1]=0;pre_tree_node(1);
    118     id=0;tp=1;pre_tree_edge(1);
    119     trlen=0;bt(1,id);
    120     for(register int i=1;i<=n;++i)change(1,ys[i],st[i]);
    121     Q=read();
    122     while(Q--)
    123     {
    124         scanf("%s",s+1);int x=read(),y=read();
    125         if(s[1]=='Q')
    126         {
    127             if(sol(x,y)!=0)printf("Yes
    ");
    128             else printf("No
    ");
    129         }
    130         else change(1,ys[x],y);
    131     }
    132     return 0;
    133 }
  • 相关阅读:
    捕获控制台输出信息
    .net 值类型变量赋值需要注意
    《河北省实施〈中华人民共和国道路交通安全法〉办法》
    在Win7应用程序中使用盾牌图标
    32位WIndows 7的“快速启动”,重启后丢失的问题,被确认是一个bug
    在本地网页中,让flash可以访问本地文件
    WPF 3D编程中,摄像机的位置很重要
    让Windows7任务栏图标显示Windows菜单(恢复,最小化,关闭)
    Joomla 书籍
    Joomla! 1.5 Template Toolbar简化Joomla模板做成的工具
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8808559.html
Copyright © 2011-2022 走看看