计蒜客 39272.Tree-树链剖分(点权)+带修改区间异或和 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest E.) 2019ICPC西安邀请赛现场赛重现赛
Ming and Hong are playing a simple game called nim game. They have nn piles of stones numbered 11 to nn ,the ii-th pile of stones has a_iai stones. There are n - 1n−1 bidirectional roads in total. For any two piles, there is a unique path from one to another. Then they take turns to pick stones, and each time the current player can take arbitrary number of stones from any pile. Of course, the current player should pick at least one stone. Ming always takes the lead. The one who takes the last stone wins this game. Ming and Hong are smart enough so they will make optimal operations every time.
m events will take place. Each event has a type called optopt ( the value of opt is among \{1,2,3 \}{1,2,3} ).
If optopt is 11, modify the numbers of stones of piles on the path from 1 to ss by the following way: change a_iai to a_i|tai∣t. ( s,ts,t will be given).
If optopt is 22 , modify the numbers of stones of piles on the path from 1 to ss by the following way: change a_iai to a_i\&tai&t. (s,ts,t will be given).
If optopt is 33 , they play nim game. Firstly, take the piles on the path from 1 to SS into consideration. At the same time create a new pile with t stones and take it into consideration. Now they have taken + 1+1 piles into consideration. Then they play nim game on these S + 1S+1 piles. You need to figure out if Ming is going to win the game. Amazingly, after playing nim game, the numbers of stones of each pile on the path from 11 to ss will return to the original numbers.
Input
Each test file contains a single test case. In each test file:
The first line contains two integers,nn and mm.
The next line contains nn integers, a_iai.
The next n - 1 lines, each line contains two integers, b, c, means there is a bidirectional road between pile b and pile c.
Each of the following mm lines contains 33 integers, optopt, ss and tt.
If optopt is 11, change all the stone numbers of piles on the path from 11 to ss in the first way (a_i(ai to a_i|t)ai∣t)
If optopt is 22, change all the stone numbers of piles on the path from 11 to ss in the second way (a_i(ai to a_i\&t)ai&t).
If optopt is 33, we query whether Ming will win when given ss and tt as parameters in this round.
It is guaranteed:1 \le n,m \le 10^51≤n,m≤105,
0 \le a_i \le 10^90≤ai≤109,
1 \le opt \le 3, 1 \le s \le 10^5, 0 \le t \le 10^9.1≤opt≤3,1≤s≤105,0≤t≤109.
Output
If optopt is 33, print a line contains one word “YES” or “NO” (without quotes) , representing whether Ming will win the game.
样例输入复制
6 6
0 1 0 3 2 3
2 1
3 2
4 1
5 3
6 3
1 3 0
2 3 1
1 1 0
3 5 0
2 4 1
3 3 1
样例输出复制
YES
NO
题意就是给你一棵点权树,有三种操作:
1.从根节点到节点u的路径上的所有点的权值&t
2.从根节点到节点u的路径上的所有点的权值|t
3.查询根节点到节点u的路径所有点的异或和是否等于t
3操作是和尼姆博奕联系起来的,分析得出以上操作。
思路:树链剖分给点重新编号然后线段树来维护。因为涉及到位运算,对于每一位建一棵线段树,建最多不超过31棵线段树。
然后每一棵线段树维护当前位上的区间异或和,当前二进制位为1的数量。若区间和为奇数说明这一位的区间异或结果为1,否则为0。
对于修改操作:
修改1为区间或操作:对于二进制的第i位,若t的二进制第i位为1,则会将从1到s的路径上的点权的二进制第i位全变为1,若t的二进制第ii位为0,则无影响
修改2为区间与操作:对于二进制的第ii位,若t的二进制第ii位为0,则会将从1到s的路径上的点权的二进制第i位全变为0,若t的二进制第ii位为1,则无影响
参考来源:
2019 ACM-ICPC 西安全国邀请赛 E-Tree 树链剖分+线段树
2019 icpc西安邀请赛 E. Tree(树链剖分+带修改的区间异或和)
我写的时候,直接按以前的板子写发现过不了,后来看的人家的题解改的过的。不知道为什么。
代码:
//E.树链剖分+线段树
//Nim和!= 0时,先手胜利,否则失败
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll; const double PI=acos(-1.0);
const double eps=1e-;
//const ll mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=1e5+;
const int maxm=+;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 int tree[][maxn<<],lazy[][maxn<<];
int n,m,r,mod;
int head[maxn],tot; int son[maxn],tid[maxn],fa[maxn],cnt,dep[maxn],siz[maxn],top[maxn];
int w[maxn],wt[maxn]; struct Edge{
int to,next;
}edge[maxn<<]; void add(int u,int v)//链式前向星存边
{
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
} void init()//初始化
{
memset(head,-,sizeof(head));
tot=;cnt=;
} //线段树部分
void pushup(int tree[],int lazy[],int rt)//上传lazy标记
{
tree[rt]=tree[rt<<]+tree[rt<<|];
if(lazy[rt<<]==lazy[rt<<|]) lazy[rt]=lazy[rt<<];
} void pushdown(int tree[],int lazy[],int rt,int m)//下放lazy标记
{
if(lazy[rt]==-){
return ;
} lazy[rt<<]=lazy[rt];
lazy[rt<<|]=lazy[rt];
tree[rt<<]=(m-(m>>))*lazy[rt];
tree[rt<<|]=(m>>)*lazy[rt];
lazy[rt]=-;
} void update(int tree[],int lazy[],int L,int R,int c,int l,int r,int rt)//区间更新
{
if(L<=l&&r<=R){
lazy[rt]=c;
tree[rt]=c*(r-l+);
return ;
} pushdown(tree,lazy,rt,r-l+);
int m=(l+r)>>;
if(L<=m) update(tree,lazy,L,R,c,lson);
if(R> m) update(tree,lazy,L,R,c,rson);
pushup(tree,lazy,rt);
} int query(int tree[],int lazy[],int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R){
return tree[rt];
} int ret=;
pushdown(tree,lazy,rt,r-l+);
int m=(l+r)>>;
if(L<=m) ret+=query(tree,lazy,L,R,lson);
if(R> m) ret+=query(tree,lazy,L,R,rson);
return ret;
} //树链剖分部分
void dfs1(int u,int father)
{
siz[u]=;//记录每个节点子树大小
fa[u]=father;//标记节点的父亲
dep[u]=dep[father]+;//标记深度
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father) continue;//如果连接的是当前节点的父亲节点,则不处理
dfs1(v,u);
siz[u]+=siz[v];//直接子树节点相加,当前节点的size加上子节点的size
if(siz[v]>siz[son[u]]){//如果没有设置过重节点son或者子节点v的size大于之前记录的重节点son,进行更新,保存重儿子
son[u]=v;//标记u的重儿子为v
}
}
} void dfs2(int u,int tp)
{
top[u]=tp;//标记每个重链的顶端
tid[u]=++cnt;//每个节点剖分以后的新编号(dfs的执行顺序)
wt[cnt]=w[u];//新编号的对应权值
if(!son[u]) return ;//如果当前节点没有处在重链上,则不处理,否则就将这条重链上的所有节点都设置成起始的重节点
dfs2(son[u],tp);//搜索下一个重儿子
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==fa[u]||v==son[u]) continue;//处理轻儿子,如果连接节点不是当前节点的重节点并且也不是u的父节点,则将其的top设置成自己,进一步递归
dfs2(v,v);//每一个轻儿子都有一个从自己开始的链
}
} void update_huo(int s,int t)
{
// int x=1,y=s;
for(int i=;i<;i++){
if(t&(<<i)){
int v=s;
while(v){
int father=top[v];
int l=tid[father],r=tid[v];
update(tree[i],lazy[i],l,r,,,n,);
v=fa[father];
} // while(top[x]!=top[y]){
// if(dep[top[x]]<dep[top[y]]) swap(x,y);//使x深度较大
// update(tree[i],lazy[i],tid[top[x]],tid[x],1,1,n,1);
// x=fa[top[x]];
// }
//
// if(dep[x]>dep[y]) swap(x,y);//使x深度较小
// update(tree[i],lazy[i],tid[x],tid[y],1,1,n,1);
}
}
} void update_yihuo(int s,int t)
{
// int x=1,y=s;
for(int i=;i<;i++){
if(t&(<<i)) continue;
int v=s;
while(v){
int father=top[v];
int l=tid[father],r=tid[v];
update(tree[i],lazy[i],l,r,,,n,);
v=fa[father];
}
// while(top[x]!=top[y]){
// if(dep[top[x]]<dep[top[y]]) swap(x,y);//使x深度较大
// update(tree[i],lazy[i],tid[top[x]],tid[x],0,1,n,1);
// x=fa[top[x]];
// }
//
// if(dep[x]>dep[y]) swap(x,y);//使x深度较小
// update(tree[i],lazy[i],tid[x],tid[y],0,1,n,1);
}
} //bool play_nim(int s,int t)
//{
// int x=1,y=s;
// int flag=0;
// for(int i=0;i<31;i++){
// int ans=0;
// while(top[x]!=top[y]){
// if(dep[top[x]]<dep[top[y]]) swap(x,y);//使x深度较大
// ans+=query(tree[i],lazy[i],tid[top[x]],tid[x],1,n,1);
// x=fa[top[x]];
// }
//
// if(dep[x]>dep[y]) swap(x,y);//使x深度较小
// ans+=query(tree[i],lazy[i],tid[x],tid[y],1,n,1);
// ans=ans&1;
// if((t&(1<<i)&&ans)||(!(t&(1<<i)&&!ans))){
// flag=1;break;
// }
// }
// if(flag) return true;
// else return false;
//} bool play_nim(int k,int s,int t)
{
// int x=1,y=s;
int ans=;
while(s){
int father=top[s];
int l=tid[father],r=tid[s];
ans+=query(tree[k],lazy[k],l,r,,n,);
s=fa[father];
}
// while(top[x]!=top[y]){
// if(dep[top[x]]<dep[top[y]]) swap(x,y);//使x深度较大
// ans+=query(tree[k],lazy[k],tid[top[x]],tid[x],1,n,1);
// x=fa[top[x]];
// }
//
// if(dep[x]>dep[y]) swap(x,y);//使x深度较小
// ans+=query(tree[k],lazy[k],tid[x],tid[y],1,n,1); ans=ans&;
if((t&(<<k))&&ans) return true;
if(!(t&(<<k))&&!ans) return true;
return false;
} int main()
{
scanf("%d%d",&n,&m);
init();
for(int i=;i<=n;i++)
scanf("%d",&w[i]);//点权
for(int i=;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs1(,);//根节点
dfs2(,);
for(int i=;i<=n;i++){//建树,每一位建一棵线段数
for(int k=;k<;k++){
if(w[i]&(<<k)) update(tree[k],lazy[k],tid[i],tid[i],,,n,);
}
}
while(m--){
int op,s,t;
scanf("%d%d%d",&op,&s,&t);
if(op==){
update_huo(s,t);
}
else if(op==){
update_yihuo(s,t);
}
// else if(op==3){
// bool ans=play_nim(s,t);
// if(ans) printf("YES\n");
// else printf("NO\n");
// } else if(op==){
int flag=;
for(int i=;i<;i++){
if(!play_nim(i,s,t)){
flag=;break;
}
}
if(flag) printf("YES\n");
else printf("NO\n");
}
}
return ;
}
计蒜客 39272.Tree-树链剖分(点权)+带修改区间异或和 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest E.) 2019ICPC西安邀请赛现场赛重现赛的更多相关文章
- 计蒜客 39280.Travel-二分+最短路dijkstra-二分过程中保存结果,因为二分完最后的不一定是结果 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest M.) 2019ICPC西安邀请赛现场赛重现赛
Travel There are nn planets in the MOT galaxy, and each planet has a unique number from 1 \sim n1∼n. ...
- 计蒜客 39279.Swap-打表找规律 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest L.) 2019ICPC西安邀请赛现场赛重现赛
Swap There is a sequence of numbers of length nn, and each number in the sequence is different. Ther ...
- 计蒜客 39270.Angel's Journey-简单的计算几何 ((The 2019 ACM-ICPC China Shannxi Provincial Programming Contest C.) 2019ICPC西安邀请赛现场赛重现赛
Angel's Journey “Miyane!” This day Hana asks Miyako for help again. Hana plays the part of angel on ...
- 计蒜客 39268.Tasks-签到 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest A.) 2019ICPC西安邀请赛现场赛重现赛
Tasks It's too late now, but you still have too much work to do. There are nn tasks on your list. Th ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12247 Accepted: 3151 Descriptio ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...
随机推荐
- 正在阅读的tex教程
https://liam.page/2014/09/08/latex-introduction/ https://www.jianshu.com/p/1d99b3c883a6 http://www.c ...
- 详解java动态代理机制以及使用场景
详解java动态代理机制以及使用场景 https://blog.csdn.net/u011784767/article/details/78281384 深入理解java动态代理的实现机制 https ...
- HTTP协议的认识
1.内容回顾 1.HTTP协议消息的格式: 1.请求(request) 请求方法 路径 HTTP/1.1 \r\n k1:v1\r\n ...\r\n \r\n 请求体 <--这里可以有可以没有 ...
- python中configparser模块读取ini文件
python中configparser模块读取ini文件 ConfigParser模块在python中用来读取配置文件,配置文件的格式跟windows下的ini配置文件相似,可以包含一个或多个节(se ...
- react diff
传统diff 通过循环递归对节点的依次对比,复杂度是O(n3) react diff react对传统diff进行了优化,将复杂度降为O(n) react基于这几个前提对diff进行了优化: 忽略跨层 ...
- JavaScript之DOM节点操作
a.appendChild(b) 追加标签 a是b的父级,将b追加到a中 追加标签 a.insertBefore(b,c); a是b和c的父级,在c前面插入b 删除标签 a.removeCli ...
- static 关键字有什么作用
static关键字的含义及使用场景 static是Java50个关键字之一.static关键字可以用来修饰代码块表示静态代码块,修饰成员变量表示全局静态成员变量,修饰方法表示静态方法.(注意:不能修饰 ...
- Devops Reference
摘自 https://www.cnblogs.com/yibutian/p/9561657.html DevOps 企业实践 实施DevOps的核心目标是加速团队.企业的IT精益运行,从根本上提升IT ...
- 高阶函数-map/filter/reduce
什么样的函数叫高阶函数: 条件:1.函数接受函数作为参数 2.函数的返回值中包含函数 高阶函数之----map函数 map(func, *iterables) --> map objectnum ...
- GDI显示图像时设定窗口大小为图像大小
先前已经能基于GDI显示png图像,但是窗口大小和图像尺寸并不一致.注意到opencv中的imshow的窗口和图像尺寸一致,这里进行设置. 原理 CreateWindow阶段并不能确定窗口大小,但是在 ...