【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 ...
随机推荐
- easyui中Tab的tools按钮刷新当前tab
easyui中Tab的tools按钮刷新当前tab 点击刷新按钮,刷新当前Tab选项卡. $('#index_tabs').tabs({ fit : true, border : false, too ...
- JAVA:变量,数据类型,运算符,流程控制(简介)<1>
一.安装和配置jdk 1.jdk是什么? (1).jdk全称是Java Development Kit, Java开发工具包; (2).jdk是sun公司开发的; (3).jdk主要包括:jre(Ja ...
- Git tricks: Unstaging files
NOTE: Following content is directly reprinted from http://andrewberls.com/blog/post/git-tricks-unsta ...
- opencv获取图片sift特征
利用opencv2.3来获取图片的sift特征,并输出到标准输出,可用重定向到文件. #include<cstdio> #include"opencv2/opencv.hpp&q ...
- bootstrap时间插件 火狐不显示 完美解决方法
原文链接:http://www.phpbiji.cn/article/index/id/141/cid/4.html bootstrap时间插件火狐 bootstrap-datetimepicker火 ...
- iOS人机界面指南(翻译)
本文源自于苹果开发者网站的文章iOS Human Interface Guidelines,内容比较多,此处仅仅是部分笔记.
- C++二维数组动态内存分配
对于二维数组和二维指针的内存的分配 这里首选说一下一维指针和一维数组的内存分配情况. 一维: 数组:形如int a[5];这里定义了一个一维数组a,并且数组的元素个数是5,这里的a是这五个元素的整体 ...
- div层遮盖flash(兼容浏览器)
今天测试div层和flash的交互,发现div层总是被flash层遮盖,在百度上找了一会,说是加个<param name="wmode" value="transp ...
- jquery插件开发模板
(function($){ $.fn.extend({ //将可选择的变量传递给方法 pluginname: function(options) { //设置默认值并用逗号隔开 var default ...
- 如何在C#中实现图片缩放
//下面给出三个简单的方法,后面两个方法是扩展,估计有时用得着 //************************************************************// /// ...