【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\n" : "No\n");
 98         }
 99         else updata(1,1,n,tid[x],y);
100     }
101     return 0;
102 }

时间: 2024-12-28 10:12:32

【BZOJ】【2819】NIM的相关文章

P2433 - 【BZOJ 3262三维偏序】陌上花开------三维偏序

P2433 - [BZOJ 3262三维偏序]陌上花开 Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量. 定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb.显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,

【BZOJ做题记录】07.07~?

在NOI一周前重开一个坑 最后更新时间:7.07 11:26 7.06 下午做的几道CQOI题: BZOJ1257: [CQOI2007]余数之和sum:把k mod i写成k-k/i*i然后分段求后面的部分就好了 BZOJ1258: [CQOI2007]三角形tri:在草稿纸上按照位置和边找一下规律就好了 BZOJ1260: [CQOI2007]涂色paint:简单的区间DP BZOJ1303: [CQOI2009]中位数图:小于中位数的改为-1大于的改为1,算一算前缀和然后哈希一下乘一乘就好

【BZOJ 2820】 YY的GCD

2820: YY的GCD Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 807  Solved: 404 [Submit][Status] Description 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对 kAc这种傻×必然不会了,于是向你来请教-- 多组输入 Input 第一行一个整数T 表述数据组数 接下来T行,每行两个正整数,表示

【BZOJ】3319: 黑白树

http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种:1.查询u到根的第一条黑边的编号.2.将u到v的路径全部染成黑色 #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream>

【bzoj】4538: [Hnoi2016]网络

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4538 维护一个数据结构支持对于一颗树的操作,需要支持: 1.对于树上的一条路径上的每个点上放一个值. 2.撤销某次操作的路劲放. 3.查询除了经过这个点的路径的最大值. 往一个路径上丢值相当于往不经过条路径的所有点上丢值. 用一个树链剖分即可维护,对于操作区间取反. 直接查询单点最大值即可. 为了维护单点最大值,线段树中的每一个点对应两个堆,用于维护插入誉删除. 防止爆空间,所以标记永久

【BZOJ】【1089】【SCOI2003】严格n元树

高精度/递推 Orz Hzwer…… 然而我想多了…… 理解以后感觉黄学长的递推好精妙啊 顺便学到了一份高精度的板子= =233 引用下题解: f[i]=f[i-1]^n+1 ans=f[d]-f[d-1] 然后加个高精度... 话说这个数据范围是虚的吧... 极限数据根本不会做.. 1 /************************************************************** 2 Problem: 1089 3 User: Tunix 4 Language:

【BZOJ】【1050】【HAOI2006】旅行comf

枚举/暴力/Kruskal orz……我sb了……其实是sb题<_< 有一道题问的是最小极差生成树……(不记得是什么名字了,就是求最大边权与最小边权差最小的生成树)做法是枚举最小边,然后kruskal找最大边 这题同理,因为$m\leq 5000$,所以$m^2$的算法即可…… 1 /************************************************************** 2 Problem: 1050 3 User: Tunix 4 Language: C

【BZOJ】【1038】【ZJOI2008】瞭望塔

计算几何/半平面交 说是半平面交,实际上只是维护了个下凸壳而已……同1007水平可见直线 对于每条线段,能看到这条线段的点都在这条线段的“上方”,那么对所有n-1条线段求一个可视区域的交,就是求一个半平面交……(好扯) 一开始我想的是:直接找到这个下凸壳的最低点,它的y值就是答案辣-但是明显不对>_>这题让求的是塔的最低高度……不光要考虑塔顶,还要看塔底的啊! 那么我们怎么找呢?我们可以发现:随着x的变化,塔高(就是地面到凸壳的竖直距离,y坐标之差)是一个分段函数,分段点就是地面的折点以及凸壳

【BZOJ】【1009】 【HNOI2008】GT考试

DP/KMP/矩阵乘法 好神的题啊……跪了跪了 $n\leq 10^9$是什么鬼……我们还是先不要考虑这个鬼畜的玩意了>_> 用类似数位DP的思路,我们可以想到一个DP方程:$f[i][j]$表示前 i 位数字,它的最后 j 位与不吉利串匹配的方案数,显然有$ans=\sum_{i=0}^x f[n][i]$ 然后就是转移的问题了= =那么依旧按照数位DP的想法(其实是硬扯到那的吧……怎么理解都可以,重点是明白转移方程)可以想到:从 i 转移到 i+1,有10种方案,其中一种会使得匹配长度+1

【BZOJ】1821: [JSOI2010]Group 部落划分 Group(最小生成树+贪心)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=1821 这题裸题. 本题要求最短距离最长,很明显,我们排序. 这里存在贪心,即我们把边权最小的全分给n个部落的内部,然后剩下的边最小的就是答案. 将边权较小的边分给k个部落,用并查集生成最小树,使得内部的边总是小于连到外部的边.然后分剩下k个点即可,剩下的k个点的那条边一定是部落之间最小的且最长的边. #include <cstdio> #include <cstring> #