【BZOJ】【2819】NIM
这题……咋说捏,其实是一道披着博弈论外衣的树上操作问题……
随便用dfs序或者树链剖分转成序列,然后查询路径上的所有点的NIM和(异或和)就行了,毕竟除了是在树上以外,就是裸的NIM问题。
树链剖分:一开始把线段树写跪了,然后输出“Yes”和“No”的时候全部大写了,再然后发现线段树空间开小了……
代码如下:
//BZOJ 2819
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
const int N=;
#define debug
int n,a[N],t[N<<],fa[N],top[N],dep[N],son[N],size[N],tid[N],cnt=;
vector<int>G[N];
bool vis[N]; #define mid (l+r>>1)
#define L (o<<1)
#define R (o<<1|1)
void updata(int o,int l,int r,int pos,int v){
if (l==r) t[o]=v;
else{
if (pos<=mid) updata(L,l,mid,pos,v);
else updata(R,mid+,r,pos,v);
t[o]=t[L]^t[R];
}
} int ql,qr,ans=;
void query_it(int o,int l,int r){
if (ql<=l && qr>=r) ans^=t[o];
else{
if (ql<=mid) query_it(L,l,mid);
if (qr>mid) query_it(R,mid+,r);
}
}
//segment tree end void dfs(int x,int f,int deep){
int y,maxsize=;
vis[x]=; fa[x]=f; dep[x]=deep; size[x]=; son[x]=;
rep(i,G[x].size()){
y=G[x][i];
if (vis[y]) continue;
dfs(y,x,deep+);
size[x]+=size[y];
if (size[y]>maxsize) maxsize=size[y],son[x]=y;
}
} void connect(int x,int f){
tid[x]=++cnt;
top[x]=f; vis[x]=;
if (son[x]) connect(son[x],f);
rep(i,G[x].size()){
int y=G[x][i];
if (!vis[y]) connect(y,y);
}
} void query(int x,int y){
while(top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
ql=tid[top[x]]; qr=tid[x];
query_it(,,n);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
ql=tid[x]; qr=tid[y];
query_it(,,n);
} int main(){
// freopen("file.in","r",stdin);
scanf("%d",&n);
F(i,,n) scanf("%d",&a[i]);
int x,y;
F(i,,n){
scanf("%d%d",&x,&y);
G[x].pb(y);
G[y].pb(x);
}
dfs(,,);
memset(vis,,sizeof vis);
connect(,);
F(i,,n) updata(,,n,tid[i],a[i]);
int q;
scanf("%d",&q);
char cmd[];
F(i,,q){
scanf("%s%d%d",cmd,&x,&y);
if (cmd[]=='Q'){
ans=;
query(x,y);
printf(ans ? "Yes\n" : "No\n");
}
else updata(,,n,tid[x],y);
}
return ;
}
dfs序版:
维护从根到x的异或和sum(x),则query(x,y)=sum(x)^sum(y)^a[lca(x,y)]
自己画个图一眼就看出来了……公共部分两次异或互相抵消,但是LCA是在x-->y这条路径上的,所以要再加上
/**************************************************************
Problem: 2819
User: Tunix
Language: C++
Result: Accepted
Time:15004 ms
Memory:65740 kb
****************************************************************/ //BZOJ 2819
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
using namespace std;
void read(int &v){
v=; int sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
v*=sign;
}
/******************tamplate*********************/
const int N=;
int head[N],to[N<<],next[N<<],cnt,fa[N];
void add(int x,int y){
to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
}
/*******************edge***********************/
int n,m,dfs_clock,l[N],r[N],t[N<<],a[N],deep[N];
int st[N],top;
void dfs(){
st[++top]=; fa[]=;deep[]=;
while(top){
int x=st[top];
if (!l[x]){
l[x]=++dfs_clock;
for(int i=head[x];i;i=next[i])
if (to[i]!=fa[x]){
st[++top]=to[i];
fa[to[i]]=x;
deep[to[i]]=deep[x]+;
}
}
else{
r[x]=++dfs_clock;
top--;
}
}
}
int p[N][];
void ST(){
memset(p,-,sizeof p);
F(i,,n) p[i][]=fa[i];
for(int j=;(<<j)<=n;++j)
F(i,,n)
if (p[i][j-]!=-) p[i][j]=p[p[i][j-]][j-];
}
int lca(int x,int y){
if (deep[x]<deep[y]) swap(x,y);
int k=log(deep[x])/log();
D(i,k,)
if (deep[x]-(<<i)>=deep[y]) x=p[x][i];
if (x==y) return y;
D(i,k,)
if (p[x][i]!=- && p[x][i]!=p[y][i]){
x=p[x][i]; y=p[y][i];
}
return p[x][];
}
/*****************dfs&LCA***********************/
inline int lowbit(int x){return x&(-x);}
void update(int x,int val){
for(x;x<=n*;x+=lowbit(x)) t[x]^=val;
}
int sum(int x){
int temp=;
for(x;x;x-=lowbit(x)) temp^=t[x];
return temp;
}
/*********************fenwick*******************/
int main(){
read(n);
F(i,,n) read(a[i]);
int x,y;
F(i,,n){
read(x); read(y);
add(x,y);
}
dfs();
ST();
F(i,,n) update(l[i],a[i]),update(r[i],a[i]);
read(m);
char cmd[];
F(i,,m){
scanf("%s",cmd);
read(x); read(y);
if (cmd[]=='Q') printf( sum(l[y])^sum(l[x])^a[lca(x,y)] ? "Yes\n" : "No\n");
else{
update(l[x],a[x]); update(r[x],a[x]);
update(l[x],y); update(r[x],y);
a[x]=y;
}
}
return ;
}
【BZOJ】【2819】NIM的更多相关文章
- 【Bzoj 1835 基站选址】
基站选址的区间里隐藏着DP优化的机密…… 分析: 不论是做过乘积最大还是石子合并,或者是其他的入门级别的区间DP题目的人呐,大米并认为读题后就能够轻松得出一个简洁明了的Dp转移方程. ...
- 【BZOJ 2744 朋友圈】
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1570 Solved: 532[Submit][Status][Discuss] Descripti ...
- 【BZOJ 5038 不打兔子】
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 22 Solved: 8[Submit][Status][Discuss] Description 勤 ...
- 【BZOJ 1088 扫雷Mine】模拟
http://www.lydsy.com/JudgeOnline/problem.php?id=1088 2*N的扫雷棋盘,第二列的值a[i]记录第 i 个格子和它8连通的格子里面雷的数目. 第一列的 ...
- 【BZOJ做题记录】07.07~?
在NOI一周前重开一个坑 最后更新时间:7.08 07:38 7.06 下午做的几道CQOI题: BZOJ1257: [CQOI2007]余数之和sum:把k mod i写成k-k/i*i然后分段求后 ...
- 【bzoj5050】【bzoj九月月赛H】建造摩天楼
讲个笑话,这个题很休闲的. 大概是这样的,昨天看到这个题,第一眼星际把题目看反了然后感觉这是个傻逼题. 后来发现不对,这个修改一次的影响是很多的,可能导致一个数突然可以被改,也可能导致一个数不能被改. ...
- 【BZOJ 4151 The Cave】
Time Limit: 5 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 293 Solved: 144[Submit][Status][Di ...
- 【BZOJ 2458 最小三角形】
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1551 Solved: 549[Submit][Status][Discuss] Descripti ...
- 【BZOJ 5000 OI树】
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 107 Solved: 64[Submit][Status][Discuss] Description ...
- 【BZOJ 5047 空间传送装置】
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 282 Solved: 121[Submit][Status][Discuss] Descriptio ...
随机推荐
- linux中mail函数不能发送邮件
没有安装或启动 sendmail 组件 解决办法 我是新手,命令不熟,所以写的很详细,老鸟勿喷哦 1.重新安装 sendmail 组件,我用的是 CentOS ,使用下面的命令安装 代码如下 复制代码 ...
- ApplicationContext的应用场景
1.上一节中我们了解了IoC容器建立的基本步骤.理解这些步骤之后,可以很方便地通过编程的方式来手工控制这些配置和容器的建立过程了. 2.但是,在Spring中,系统已经为用户提供了许多已经定义好的容器 ...
- ListView Web 服务器控件概述(MSDN)
1: "折叠"图像"展开"图像"复制"图像"复制悬停"图像 全部折叠全部展开 代码:全部 代码:多个 代码:Visual ...
- 在别的地方看的<<给程序员介绍一些C++开源库>>,记录给大家共同学习
首先说明这篇文章不是出自我手,大家共同学习. 引用地址:http://oss.org.cn/?action-viewnews-itemid-61998. C++开源库,欢迎补充. C++在“商业应用” ...
- 转:JAVA中this用法小结
转:http://blog.sina.com.cn/s/blog_6a6badc90100t8hm.html#SinaEditor_Temp_FontName Java关键字this只能用于方法方法体 ...
- 自制小工具监控wcf服务是否正常
由于项目中有2个使用netTcpBinding的wcf服务经常出现无法提供服务的问题,一直找原因也找不到导致影响严重,更换InstanceContextMode和ConcurrencyMode配置也不 ...
- 【Qt】Qt之密码框不可选中、复制、粘贴、无右键菜单等【转】
简述 在做用户登录.修改密码的时候,往往会用到密码框,其中一些功能要求与普通的输入框不同,例如:不能选中.复制.粘贴.无右键菜单等功能,当然设置密码不可见是必须的! 下面介绍两种方式来实现相同的效果. ...
- 【原】去掉UltraGrid第三方控件中的Drag a column header here to group by that column
- php随机验证码
今天同学问我,用php怎么写验证码,由于是新手所以花了半天的时间才完成.而且功能很是简单呵呵.今天本来打算写session和cookie的看来是要明天了. <?php $image_width= ...
- CLR via C# 混合线程同步构造
1. 自旋,线程所有权和递归 2. 混合构造 a.ManualResetEventSlim b.SemaphoreSlim c.Monitor d.ReaderWriterLockSlim 3.条件变 ...