【BZOJ2908】又是nand 树链剖分+线段树
【BZOJ2908】又是nand
escription
Input
Output
对于操作②每个输出一行,如题目所述。
Sample Input
2 7 3
1 2
2 3
Query 2 3
Replace 1 3
Query 1 1
Sample Output
7
题解:网上都说要拆位,那么我也拆位吧~(不拆位好像也能做?)
首先,nand满足交换律但不满足结合律。
我们先树剖,然后对于每一位,都用线段树维护tl[d][x],代表如果该位是d,从左边来经过这个区间后会变成的数,tr[d][x]代表如果该位是d,从右往左经过这个区间后会变成的数。然后就是区间合并的事了~
对于询问a,b,我们先求出从a向上走到lca的变化,再求出从lca向下走到b的变化即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#define lson x<<1
#define rson x<<1|1
using namespace std;
int n,m,k,cnt;
char str[10];
const int maxn=100010;
int to[maxn<<1],next[maxn<<1],head[maxn],fa[maxn],dep[maxn],siz[maxn],top[maxn],son[maxn],p[maxn],q[maxn],st[maxn];
unsigned v[maxn];
struct seg
{
bool tl[2][maxn<<2],tr[2][maxn<<2];
void pushup(int x)
{
tl[0][x]=tl[tl[0][lson]][rson],tl[1][x]=tl[tl[1][lson]][rson];
tr[0][x]=tr[tr[0][rson]][lson],tr[1][x]=tr[tr[1][rson]][lson];
}
void build(int l,int r,int x,int a)
{
if(l==r)
{
tl[0][x]=tr[0][x]=1,tl[1][x]=tr[1][x]=!((v[q[l]]>>a)&1);
return ;
}
int mid=l+r>>1;
build(l,mid,lson,a),build(mid+1,r,rson,a);
pushup(x);
}
void updata(int l,int r,int x,int a,bool b)
{
if(l==r)
{
tl[0][x]=tr[0][x]=1,tl[1][x]=tr[1][x]=!b;
return ;
}
int mid=l+r>>1;
if(a<=mid) updata(l,mid,lson,a,b);
else updata(mid+1,r,rson,a,b);
pushup(x);
}
bool ql(int l,int r,int x,int a,int b,bool c)
{
if(a<=l&&r<=b) return tl[c][x];
int mid=l+r>>1;
if(b<=mid) return ql(l,mid,lson,a,b,c);
if(a>mid) return ql(mid+1,r,rson,a,b,c);
return ql(mid+1,r,rson,a,b,ql(l,mid,lson,a,b,c));
}
bool qr(int l,int r,int x,int a,int b,bool c)
{
if(a<=l&&r<=b) return tr[c][x];
int mid=l+r>>1;
if(b<=mid) return qr(l,mid,lson,a,b,c);
if(a>mid) return qr(mid+1,r,rson,a,b,c);
return qr(l,mid,lson,a,b,qr(mid+1,r,rson,a,b,c));
}
}s[33];
inline int rd()
{
int ret=0; char gc=getchar();
while(gc<'0'||gc>'9') gc=getchar();
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret;
}
void dfs1(int x)
{
siz[x]=1;
for(int i=head[x];i!=-1;i=next[i])
{
if(to[i]!=fa[x])
{
fa[to[i]]=x,dep[to[i]]=dep[x]+1,dfs1(to[i]),siz[x]+=siz[to[i]];
if(siz[to[i]]>siz[son[x]]) son[x]=to[i];
}
}
}
void dfs2(int x,int tp)
{
top[x]=tp,p[x]=++p[0],q[p[0]]=x;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
}
void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void ask(int x,int y)
{
unsigned int ret=0;
int i;
st[0]=0;
while(top[x]!=top[y])
{
if(dep[top[x]]>=dep[top[y]])
{
for(i=0;i<k;i++) ret=ret-(ret&(1<<i))+(s[i].qr(1,n,1,p[top[x]],p[x],(ret>>i)&1)<<i);
x=fa[top[x]];
}
else st[++st[0]]=y,y=fa[top[y]];
}
if(dep[x]<dep[y]) for(i=0;i<k;i++) ret=ret-(ret&(1<<i))+(s[i].ql(1,n,1,p[x],p[y],(ret>>i)&1)<<i);
else for(i=0;i<k;i++) ret=ret-(ret&(1<<i))+(s[i].qr(1,n,1,p[y],p[x],(ret>>i)&1)<<i);
for(y=st[0];y;y--) for(i=0;i<k;i++) ret=ret-(ret&(1<<i))+(s[i].ql(1,n,1,p[top[st[y]]],p[st[y]],(ret>>i)&1)<<i);
printf("%u\n",ret);
}
int main()
{
n=rd(),m=rd(),k=rd();
int i,j,a,b;
for(i=1;i<=n;i++) scanf("%u",&v[i]);
memset(head,-1,sizeof(head));
for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
dep[1]=1,dfs1(1),dfs2(1,1);
for(i=0;i<k;i++) s[i].build(1,n,1,i);
for(i=1;i<=m;i++)
{
scanf("%s",str);
if(str[0]=='Q') a=rd(),b=rd(),ask(a,b);
else
{
a=rd(),scanf("%u",&v[a]);
for(j=0;j<k;j++) s[j].updata(1,n,1,p[a],(v[a]>>j)&1);
}
}
return 0;
}//3 3 3 2 7 3 1 2 2 3 Query 2 3 Replace 1 3 Query 1 1
【BZOJ2908】又是nand 树链剖分+线段树的更多相关文章
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
随机推荐
- 拓扑排序(附LeetCode题目)
算法期中考到一题关于拓扑序的题目,觉得很值得一写. 1.什么是拓扑序? 对一个有向无环图进行拓扑排序,假如图中存在一条从顶点A到顶点B的路径,则拓扑序中顶点A出现在顶点B的前面.要注意的是,这是对有向 ...
- UVA 10288 Coupons (概率)
题意:有n种纸片无限张,随机抽取,问平均情况下抽多少张可以保证抽中所有类型的纸片 题解:假设自己手上有k张,抽中已经抽过的概率为 s=k/n:那抽中下一张没被抽过的纸片概率为 (再抽一张中,两张中,三 ...
- eclipse中去掉警告提示
有时候我们要去掉这些不必要的提示 下面我们来设置去掉这些警告提示
- TCP的滑动窗口
TCP发送方的窗口可以划分成四个部分: 1.已经发送并且确认的TCP段: 2.已经发送但是没有确认的TCP段: 3.未发送但是接收方准备接收的TCP段, 4.未发送并且接收方也为准备接受的TCP段. ...
- Java 关于assert
昨天在看NIO源码的时候,看到这样一句,顿时懵逼了 : assert (i >= 0); assert关键词我是有映像的, 中文叫断言.但是从来没有去了解过它的功能, 今天在感冒中抽出时间, 把 ...
- js 格式化时间日期函数小结3
function DateUtil(){}/***功能:格式化时间*示例:DateUtil.Format("yyyy/MM/dd","Thu Nov 9 20:30:37 ...
- web自动化常用定位和方法总结
一. driver常用方法 二. 常用定位 三. 元素在页面不可见区域 四. iframe的操作 五. 页面弹出框:加等待时间 六. windows弹出框 七. 鼠标操作 八. 下拉列表 注意:下图中 ...
- [MYSQL]时间毫秒数转换
java中常用bigint字段保存时间,通常将时间保存为一大串数字,每次取出需要在程序里转换,有时候程序里不方便,可以使用MYSQL自带的函数FROM_UNIXTIME(unix_timestamp, ...
- JavaScript高级程序设计读后感(一)
一.什么是JavaScript? 本质? 历史? 表单验证发展成为一门语言 局限性?
- LeetCode OJ:Compare Version Numbers(比较版本字符串)
Compare two version numbers version1 and version2.If version1 > version2 return 1, if version1 &l ...