bzoj3553: [Shoi2014]三叉神经树 树链剖分
来源:互联网 发布:易订货源码下载 编辑:程序博客网 时间:2024/04/28 22:49
此题的完成,代表近期的树链剖分就告一段落,全力进入联赛复习。
省选day2 的第二题,当时只是写了裸的bfs,TE到家了。
4个月后学长偶然的一句:树链剖分也可以,考试的时候就vfk一个人想到了。。。
如今看来,vfk走出考场说“今天三个题都是暴力”,是正确的。
由于每次改变根节点,那么这个到1的路径上的点才有可能更新。
当根节点由0变为1时,只会对上一个节点是1的点有影响,如果不是1直接更新这个点就可以了。
反过来 一个根节点由1变为0时,只会对上一个节点是2的产生影响。
val记录这个点有几个值为1的儿子
可是线段树如何介入呢。
这就是vfk的那句暴力了。
如果这个点由0变为了1,那么他所有的父节点中连续的只有一个子节点为1 即val[ i ]==1的点的值都会变为1;
如果这个点由1变为了0,那么他所有的父节点中连续的只有两个子节点为1 即val[ i ]==2的点的值都会变为0;
(建议自己画个图看一下)
这里就把O(n)的修改降为了O(logn);
所以线段树只需维护区间左右连续的值的长度即可。
每一次update后都要判断有没有到根节点。
/************************************************************** Problem: 3553 User: xujiahe Language: C++ Result: Accepted Time:23080 ms Memory:175812 kb****************************************************************/ #include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cmath>#include <queue>using namespace std;#define maxn 2100000#define ll long long#define lson rt<<1,l,m#define rson rt<<1|1,m+1,r#define ss printf("orz\n")inline int readint(){ int flag=0; char ch = getchar(); int data = 0; while (ch < '0' || ch > '9') { if(ch=='-') flag=1; ch = getchar(); } do { data = data*10 + ch-'0'; ch = getchar(); }while (ch >= '0' && ch <= '9'); if(flag) data=-data; return data;}int fa[maxn],siz[maxn],top[maxn],w[maxn],son[maxn],dep[maxn],id,dy[maxn],nn,val2[maxn];struct node{ int v,next;}g[maxn];int num,n,first[maxn],val[maxn];int tree[maxn],col[maxn],lcol[maxn],rcol[maxn],lmax[maxn],rmax[maxn],sum[maxn];void build(int a,int b){ num++; g[num].v=b; g[num].next=first[a]; first[a]=num;}void dfs(int now){ if (now>nn) return; int v,ceng; int maxv=0,flag=0,tmp=0; siz[now]=1; for(int i=first[now];i;i=g[i].next) { v=g[i].v; if(v==fa[now]) continue; dfs(v); dep[v]=dep[now]+1; fa[v]=now; val2[now]+=val[v]; if(val[v]) { tmp++; } siz[now]+=siz[v]; if(siz[v]>maxv) { maxv=siz[v]; flag=v; } } son[now]=flag; if(tmp>1) val[now]=1; else val[now]=0;}void getid(int now,int root){ if(now>nn) return; w[now]=++id; top[now]=root; dy[id]=now; if(son[now]) getid(son[now],top[now]); for(int i=first[now]; i; i=g[i].next) { if(g[i].v!=son[now]&&g[i].v!=fa[now]) { getid(g[i].v,g[i].v); } }}void pushdown(int rt){ if(col[rt]!=0) { col[rt<<1]+=col[rt]; col[rt<<1|1]+=col[rt]; lcol[rt<<1]+=col[rt]; rcol[rt<<1]+=col[rt]; lcol[rt<<1|1]+=col[rt]; rcol[rt<<1|1]+=col[rt]; col[rt]=0; }}void pushup(int rt,int len){ lmax[rt]=lmax[rt<<1]; if(lmax[rt<<1]==(len-(len>>1))&&rcol[rt<<1]==lcol[rt<<1|1]) { lmax[rt]+=lmax[rt<<1|1]; } rmax[rt]=rmax[rt<<1|1]; if(rmax[rt<<1|1]==(len>>1)&&rcol[rt<<1]==lcol[rt<<1|1]) { rmax[rt]+=rmax[rt<<1]; } lcol[rt]=lcol[rt<<1]; rcol[rt]=rcol[rt<<1|1];}void buildt(int rt,int l,int r){ int m=(l+r)>>1; if(l==r) { lmax[rt]=rmax[rt]=1; lcol[rt]=rcol[rt]=val2[dy[l]]; return ; } buildt(lson); buildt(rson); pushup(rt,r-l+1);}int getval(int rt,int l,int r,int x){ int m=(l+r)>>1; if(l==r) { return lcol[rt]; } pushdown(rt); if(x<=m) { return getval(lson,x); } else { return getval(rson,x); } }int getlen(int rt,int l,int r,int x,int y){ if(x==l&&y==r) { return rmax[rt]; } pushdown(rt); int tmp=0; int m=(l+r)>>1; if(y<=m) { return getlen(lson,x,y); } else if(x>m) { return getlen(rson,x,y); } else { tmp=getlen(rson,m+1,y); if (tmp<y-m||rcol[rt<<1]!=lcol[rt<<1|1]) return tmp; else return tmp+getlen(lson,x,m); }}void update(int rt,int l,int r,int x,int y,int c){ if(x==l&&y==r) { lcol[rt]+=c; rcol[rt]+=c; col[rt]+=c; return; } pushdown(rt); int m=(l+r)>>1; if(y<=m) { update(lson,x,y,c); } else if(x>m) { update(rson,x,y,c); } else { update(lson,x,m,c); update(rson,m+1,y,c); } pushup(rt,r-l+1);}void getans(int x,int op){ int xx=x; if(op==1) { while(x) { if(getval(1,1,n,w[x])!=1) { update(1,1,n,w[x],w[x],1); break; } int len=getlen(1,1,n,w[top[x]],w[x]); update(1,1,n,max(w[x]-len+1,1),w[x],1); if (max(w[x]-len+1,1)!=1 && len!=w[x]-w[top[x]]+1) { update(1,1,n,w[fa[dy[w[x]-len+1]]],w[fa[dy[w[x]-len+1]]],1); } if (len!=w[x]-w[top[x]]+1) break; x=fa[top[x]]; } } else { while(x) { if(getval(1,1,n,w[x])!=2) { update(1,1,n,w[x],w[x],-1); break; } int len=getlen(1,1,n,w[top[x]],w[x]); update(1,1,n,max(w[x]-len+1,1),w[x],-1); if (max(w[x]-len+1,1)!=1 && len!=w[x]-w[top[x]]+1) { update(1,1,n,w[fa[dy[w[x]-len+1]]],w[fa[dy[w[x]-len+1]]],-1); } if (len!=w[x]-w[top[x]]+1) break; x=fa[top[x]]; } }}int main(){ char str[20]; int a,b,c,m; n=readint(); nn=n; for(int i=1;i<=n;i++) { a=readint(); b=readint(); c=readint(); build(i,a); build(i,b); build(i,c); } for(int i=1;i<=2*n+1;i++) { val[i+n]=readint(); } n=n*3+1; fa[1]=0; dfs(1); getid(1,1); int x,y,z; n=nn; memset(col,0,sizeof(col)); buildt(1,1,n); m=readint(); while(m--) { x=readint(); if(val[x]==0) { val[x]^=1; getans(fa[x],1); } else { val[x]^=1; getans(fa[x],2); } printf("%d\n",getval(1,1,n,1)>1); } return 0;}/*32 3 45 6 78 9 100 0 0 0 1 1 1544568////////////10011*/
0 0
- bzoj3553: [Shoi2014]三叉神经树 树链剖分
- bzoj 3553: [Shoi2014]三叉神经树
- bzoj3553
- bzoj3562: [SHOI2014]神奇化合物
- 【SHOI2014】【BZOJ3566】概率充电器
- [bzoj3566][SHOI2014]概率充电器
- [bzoj3566][SHOI2014]概率充电器
- 【bzoj3566】 [SHOI2014]概率充电器
- BZOJ3566: [SHOI2014]概率充电器
- bzoj3566 [SHOI2014]概率充电器
- 3562: [SHOI2014]神奇化合物
- [SHOI2014]概率充电器 dp
- [SHOI2014]神奇化合物解题报告
- BZOJ 3566 [SHOI2014]概率充电器
- 【BZOJ3562】【SHOI2014】神奇化合物 特技
- bzoj3566: [SHOI2014]概率充电器 dp
- bzoj3564: [SHOI2014]信号增幅仪
- bzoj 3566: [SHOI2014]概率充电器
- bwt - search 算法
- 从0搭建RAC实验环境(二)
- svn 在centos中部署 以及hook
- jordan spizike Peninsula Network - � Read tipsDespite the care of three men tired unbearable
- toms outlet store the man got into the operating room. The anterior wall of the right ventricle of
- bzoj3553: [Shoi2014]三叉神经树 树链剖分
- Tempter of the Bone (dfs)
- 第二部分面向对像基础第五章下半部分与习题总结
- 法规和人格地方个地方哥哥
- 黑马程序员——Object 类,String类,StringBuffer/StringBuilder类,基本数据类型封装类
- 卡特兰数应用
- http://www.hao123.com/?tn=99926604_hao_pg
- 面向对象程序设计思想的魅力
- android 让自己的Activity只创建一个实例