SPOJ QTree6 [树链剖分]
来源:互联网 发布:水果软件虚拟键盘 编辑:程序博客网 时间:2024/06/02 05:28
啊啊啊!!!
maintain的时候忘记+1s+1,于是就。。。累死了,只剩下最后一个Qtree7.
这道题与上道题类似,关键在于路径上面判定同色,关键点在findpath上,至于线段树,我又一次惊叹于线段树在序列问题上近乎无敌的维护效率。中间的mid与mid+1的判定神来之笔。
看来我就是一只菜鸡。
#include<deque>#include<vector>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int N = 100100;#define mid ((l+r)>>1)struct data{ int next,to;}E[N<<2];struct node{ int l,r,ret; node(int l=0,int r=0,int s=1):l(l),r(r),ret(s){}}tree[N<<2];bool G,H;int n,q,x,y,z;int head[N],sz[N],top[N],dfn[N],tot,cnt,fa[N],dft[N],sum[N],son[N];int ls[N<<2],rs[N<<2],root[N],val[N][2],col[N],bct;inline void addedge(int x,int y){ E[++tot].to=y,E[tot].next=head[x],head[x]=tot; E[++tot].to=x,E[tot].next=head[y],head[y]=tot;}inline void dfsf(int u){ sz[u]=1; for(register int v,i=head[u];i;i=E[i].next) if(v=E[i].to,v!=fa[u]){ fa[v]=u,dfsf(v),sz[u]+=sz[v]; if(sz[son[u]]<sz[v])son[u]=v; }}inline void dfss(int u,int f){ top[u]=f,dft[dfn[u]=++cnt]=u,sum[f]++; if(son[u])dfss(son[u],f); for(register int v,i=head[u];i;i=E[i].next) if(v=E[i].to,v!=fa[u]&&v!=son[u])dfss(v,v);}void maintain(int rt,int x){ tree[rt].l=tree[rt].r=val[x][col[x]]+1;}inline node merge(node &x,node &y,bool b){ node rt=node(x.l,y.r); if(b&&x.ret)rt.l=x.l+y.l; if(b&&y.ret)rt.r=y.r+x.r; rt.ret=b&&y.ret&&x.ret; return rt;}inline void build(int rt,int l,int r){ if(l==r){ int u=dft[l]; for(register int v,i=head[u];i;i=E[i].next) if(v=E[i].to,v!=fa[u]&&top[u]!=top[v]){ build(root[v]=++bct,dfn[v],dfn[v]+sum[v]-1), val[u][col[v]]+=tree[root[v]].l; } maintain(rt,u); }else{ build(ls[rt]=++bct,l,mid),build(rs[rt]=++bct,mid+1,r); tree[rt]=merge(tree[ls[rt]],tree[rs[rt]],col[dft[mid]]==col[dft[mid+1]]); }}inline bool judge(int rt,int l,int r,int L,int R,int ret=1){ if(l==r)return ret; if(L<=mid)ret&=judge(ls[rt],l,mid,L,R); if(mid<R)ret&=judge(rs[rt],mid+1,r,L,R); if(L<=mid&&R>mid)ret&=col[dft[mid]]==col[dft[mid+1]]; return ret;}deque<int> Q;inline void findpath(int x,bool flag){ Q.clear(); while(x){ int f=top[x]; if(flag){ if(!judge(root[f],dfn[f],dfn[x]+sum[f]-1,dfn[f],dfn[x])||col[fa[f]]!=col[f]||!fa[f]){ Q.push_front(x),Q.push_front(f);break; } }else Q.push_front(x),Q.push_front(f); x=fa[f]; }}inline void update(int rt,int l,int r,int x){ if(l==r){ int f=dft[l]; if(x+2<Q.size()){ int t=Q[x+1]; val[f][col[t]]-=tree[root[t]].l; update(root[t],dfn[t],dfn[t]+sum[t]-1,x+2); val[f][col[t]]+=tree[root[t]].l; }else col[f]=1-col[f]; maintain(rt,f); }else{ if(dfn[Q[x]]<=mid)update(ls[rt],l,mid,x); else update(rs[rt],mid+1,r,x); tree[rt]=merge(tree[ls[rt]],tree[rs[rt]],col[dft[mid]]==col[dft[mid+1]]); }}inline int query(int rt,int l,int r,int x,bool &L,bool &R,int res=0){ if(l==r)return tree[rt].l; if(dfn[Q[x]]<=mid){ res+=query(ls[rt],l,mid,x,L,R); if(R&&col[dft[mid+1]]==col[dft[mid]])res+=tree[rs[rt]].l; R=R&&tree[rs[rt]].ret&&col[dft[mid+1]]==col[dft[mid]]; }else{ res+=query(rs[rt],mid+1,r,x,L,R); if(L&&col[dft[mid+1]]==col[dft[mid]])res+=tree[ls[rt]].r; L=L&&tree[ls[rt]].ret&&col[dft[mid+1]]==col[dft[mid]]; } return res;}inline void change(int u){ findpath(u,0); update(1,1,sum[1],1);}inline void ask(int u){ findpath(u,1),u=Q[0]; printf("%d\n",query(root[u],dfn[u],dfn[u]+sum[u]-1,1,G=1,H=1));}inline void read(int &res){ static char ch;int flag=1; while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48; while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;}int main(){ read(n); for(register int i=1;i<n;i++)read(x),read(y),addedge(x,y); read(q),dfsf(1),dfss(1,1); build(root[1]=++bct,1,sum[1]); for(register int i=1;i<=q;++i){ read(x),read(y); if(x)change(y); else ask(y); } return 0;}
阅读全文
0 0
- SPOJ QTree6 [树链剖分]
- SPOJ QTREE6 lct
- QTREE6
- Qtree6
- SPOJ 16549 QTREE6 - Query on a tree VI
- spoj 375 (树链剖分)
- SPOJ 375 树链剖分
- 【转】SPOJ 375 树链剖分
- spoj 375 树链剖分模板
- SPOJ - QTREE (树链剖分)
- 【SPOJ QTREE】树链剖分模板
- SPOJ 375 树链剖分学习
- SPOJ QTREE(树链剖分)
- SPOJ 375 树链剖分
- SPOJ 375 树链剖分
- SPOJ 375 树链剖分
- SPOJ 375 树链剖分
- 树链剖分模板(spoj 375)
- socket编程之组播实现(windows下c++实现)
- 20170710
- 有关项目依赖包发生 Manifest Merge 冲突的详细解决方案
- admob_注意事项_高级技巧
- ubutu 安装nginx
- SPOJ QTree6 [树链剖分]
- 两台备库设置server_id一致出现的问题
- [Ext JS 6 By Example 翻译] 第2章
- 【差分约束系统】POJ1201[Intervals]题解
- C++之虚函数、虚函数表的内存分布
- [Ext JS 6 By Example 翻译] 第3章
- gfojzy_13 脑洞记搜
- Ubuntu14.04 Linux x86_64 Kernel Compiler
- [Ext JS 6 By Example 翻译] 第4章