【bzoj3637】Query on a tree VI

来源:互联网 发布:mac有安卓模拟器 编辑:程序博客网 时间:2024/06/04 01:01

似乎是code chef上的题,不知为何bzoj也有。

题意:每个节点有颜色,刚开始可能是白色,每次修改一个点的颜色,或者询问一个点所在同色连通块的大小

此题考虑维护一个点只考虑其子树时,颜色为白色和黑色的连通块大小。

显然需要树链剖分+树状数组

然后询问就是跳到深度最小的跟它同色的祖先。

修改也是同理。

然后考虑怎么找到深度最小的同色祖先。

每次判断所在重链是否全为它的颜色。若是,就跳过,不是,就在链上二分查找位置。

时间复杂度o(nlogn^2)

#include <bits/stdc++.h>#define gc getchar()#define N 100009#define inf 0x3f3f3f3f#define ll long long#define mid (l+r>>1)using namespace std;int n,first[N],number,m,fa[N],size[N],Mson[N],deep[N],top[N],cnt,dfn[N];int bit[N][3],color[N],x,y,op,id[N];//0:black 1:whitestruct edge{int to,next;void add(int x,int y){to=y,next=first[x],first[x]=number;}}e[N<<1];int read(){int x=1;char ch;while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;int s=ch-'0';while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0';return s*x;}int lowbit(int x){return x&(-x);}void add(int x,int y,int k){for (;x<=n;x+=lowbit(x)) bit[x][k]+=y;}int qry(int x,int k,int ret=0){for (;x;x-=lowbit(x)) ret+=bit[x][k];return ret; }void dfs(int x){size[x]=1;deep[x]=deep[fa[x]]+1;for (int i=first[x];i;i=e[i].next)if (e[i].to!=fa[x]){fa[e[i].to]=x;dfs(e[i].to);size[x]+=size[e[i].to];if (size[e[i].to]>size[Mson[x]]) Mson[x]=e[i].to;}}void Dfs(int x,int y){id[dfn[x]=++cnt]=x;top[x]=y;if (Mson[x]) Dfs(Mson[x],y);for (int i=first[x];i;i=e[i].next)if (e[i].to!=fa[x]&&e[i].to!=Mson[x]) Dfs(e[i].to,e[i].to); }void ins(int x,int y,int z,int k){for (;top[x]!=top[y];x=fa[top[x]]){if (deep[top[x]]<deep[top[y]]) swap(x,y);add(dfn[top[x]],z,k),add(dfn[x]+1,-z,k);}if (deep[x]>deep[y]) swap(x,y);add(dfn[x],z,k),add(dfn[y]+1,-z,k);}int get_anc(int x){int c=color[x];while (top[x]!=1){int q=qry(dfn[x],2)-qry(dfn[top[x]]-1,2);if (q==c*(dfn[x]-dfn[top[x]]+1)){if (color[fa[top[x]]]!=c) return top[x];else x=fa[top[x]];}else{int l=dfn[top[x]],r=dfn[x],ret=0;while (l<=r){if (qry(r,2)-qry(mid-1,2)!=c*(r-mid+1))l=mid+1;else ret=mid,r=mid-1;}return id[ret];}}int l=dfn[1],r=dfn[x],ret=0;while (l<=r){if (qry(r,2)-qry(mid-1,2)!=c*(r-mid+1))l=mid+1;else ret=mid,r=mid-1;}return id[ret];}int main(){n=read();for (int i=1;i<n;i++)x=read(),y=read(),e[++number].add(x,y),e[++number].add(y,x);fa[1]=1;dfs(1);Dfs(1,1);for (int i=1;i<=n;i++)add(dfn[i],size[i],0),add(dfn[i]+1,-size[i],0);add(1,1,1);m=read();for (int i=1;i<=m;i++){op=read(),x=read();if (op==0) printf("%d\n",qry(dfn[y=get_anc(x)],color[x]));else{if (x>1) ins(fa[x],fa[y=get_anc(x)],-qry(dfn[x],color[x]),color[x]);add(dfn[x],(color[x]^=1)?1:-1,2);if (x>1) ins(fa[x],fa[y=get_anc(x)],qry(dfn[x],color[x]),color[x]);}}return 0;}


原创粉丝点击