bzoj 3553: [Shoi2014]三叉神经树

来源:互联网 发布:多益网络c 面试 编辑:程序博客网 时间:2024/05/17 02:43

题目大意:给你一棵树,除了叶子结点外每个点的都是三个儿子,每个结点都有一个状态0 or 1,每个非叶子结点的状态是其儿子中较多的那种,叶子结点的状态是给定的,支持修改与查询操作,即改变一个叶子结点的状态,或者查询根结点的状态。 n<=500000 m<=500000


    首先,树链剖分一下(叶子结点不要管),然后对于线段树上维护每个结点的状态(儿子中有几个是1),然后如果是把一个点从0改成1,那么就查询从他父亲到根结点最近的不是(1,0,0)的点x,然后把它到x的全改为(1,1,0),然后查询x->fa的状态,然后修改成多一个1的状态。1改0的话类似。。。   
    查询的话,就是线段树中单点查询了
    线段树中只需要维护右起最长连续的(0,0,1),与右起最长连续的(0,1,1)就ok了
    复杂度的话   修改log^2n,查询logn

#include<cmath>#include<cstdio>#include<cstring>#include<cassert>#include<iostream>#include<algorithm>using namespace std;const int maxn=500011,maxm=1500011,ncov=-1;inline void read(int &x){x=0; char ch=getchar();while (!isdigit(ch)) ch=getchar();for (;isdigit(ch);ch=getchar()) x=x*10+ch-'0';}inline void read_(int &x){char ch=getchar(); while (!isdigit(ch)) ch=getchar(); x=ch-'0';}int map[maxn][3],v[maxm],fa[maxm],n;void init(){read(n);for (int i=1;i<=n;++i) for (int j=0;j<3;++j) read(map[i][j]),fa[map[i][j]]=i;for (int i=n+1,m=3*n+1;i<=m;++i) read_(v[i]),v[fa[i]]+=v[i];}int dep[maxn],top[maxn],sz[maxn],dfn[maxn],seq[maxn];void getseq(){static int q[maxn]; dep[1]=1; fa[1]=0; q[1]=1;for (int i=1,w=1;i<=n;++i) for (int j=0;j<3;++j) if (map[q[i]][j]<=n)q[++w]=map[q[i]][j],dep[q[w]]=dep[q[i]]+1;for (int i=1;i<=n;++i) top[i]=i,sz[i]=1;for (int i=n;i>=1;--i) sz[fa[q[i]]]+=sz[q[i]]; sz[0]=0; dfn[1]=1;for (int i=1;i<=n;++i){int x=q[i],res=dfn[x],tmp=0;for (int j=0;j<3;++j) if (map[x][j]<=n && sz[map[x][j]]>sz[tmp]) tmp=map[x][j];if (tmp){dfn[tmp]=res+1; res+=sz[tmp]; top[tmp]=top[x];}for (int j=0;j<3;++j) if (map[x][j]<=n && map[x][j]!=tmp)dfn[map[x][j]]=res+1,res+=sz[map[x][j]];}for (int i=1;i<=n;++i)assert(dfn[i]>=0 && dfn[i]<=n && dep[i]>0 && sz[i]>0 && top[i]>0 && sz[i]<=n && top[i]<=n);for (int i=n;i>=1;--i) if (v[q[i]]>=2) ++v[fa[q[i]]];for (int i=1;i<=n;++i) seq[dfn[i]]=i;}struct Tseg{struct node{int mx[2],c,sz; // mx[0]代表(0,0,1)的右起连续最长,mx[1]代表(0,1,1)的void cov(int c_){c=c_; mx[0]=mx[1]=0; if (c==1) mx[0]=sz; if (c==2) mx[1]=sz;}}t[maxn<<3];void update(node &p,node ls,node rs){p.sz=ls.sz+rs.sz; p.mx[0]=rs.mx[0]; p.mx[1]=rs.mx[1];if (rs.mx[0]==rs.sz) p.mx[0]+=ls.mx[0];if (rs.mx[1]==rs.sz) p.mx[1]+=ls.mx[1];}void pushdown(int p){if (t[p].c==ncov) return;t[p<<1].cov(t[p].c); t[p<<1|1].cov(t[p].c); t[p].c=ncov;}void build(int p,int l,int r){t[p].c=ncov; if (l==r){t[p].sz=1; t[p].cov(v[seq[l]]); return;}int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r);update(t[p],t[p<<1],t[p<<1|1]);}void clear(){build(1,1,n);}int Query(int p,int l,int r,int m){if (l==r){assert(l==m); return t[p].c;}pushdown(p); int mid=(l+r)>>1;if (m<=mid) return Query(p<<1,l,mid,m);return Query(p<<1|1,mid+1,r,m);}node Query(int p,int l,int r,int fir,int las){if (l==fir && r==las) return t[p];pushdown(p); int mid=(l+r)>>1;if (las<=mid) return Query(p<<1,l,mid,fir,las);if (fir>mid) return Query(p<<1|1,mid+1,r,fir,las);node res; update(res,Query(p<<1,l,mid,fir,mid),Query(p<<1|1,mid+1,r,mid+1,las));return res;}void modify(int p,int l,int r,int fir,int las,int c){if (l==fir && r==las) {t[p].cov(c); return;}pushdown(p); int mid=(l+r)>>1;if (las<=mid) modify(p<<1,l,mid,fir,las,c);else if (fir>mid) modify(p<<1|1,mid+1,r,fir,las,c);else modify(p<<1,l,mid,fir,mid,c),modify(p<<1|1,mid+1,r,mid+1,las,c);update(t[p],t[p<<1],t[p<<1|1]);}void modify(int x,int p,int c){for (;top[x]!=top[p];x=fa[top[x]]) modify(1,1,n,dfn[top[x]],dfn[x],c);modify(1,1,n,dfn[p],dfn[x],c);}int modify(int x){int key=v[x]; v[x]=1-v[x];// 把key变成1-keyint tmp=fa[x];while (1){node res=Query(1,1,n,dfn[top[tmp]],dfn[tmp]);if (res.sz!=res.mx[key]) break; tmp=top[tmp];if (!fa[tmp]) break;if (Query(1,1,n,dfn[fa[tmp]])!=key+1) break; tmp=fa[tmp];}int p;if (Query(1,1,n,dfn[tmp])!=key+1){modify(1,1,n,dfn[tmp],dfn[tmp],Query(1,1,n,dfn[tmp])+(key?-1:1));return Query(1,1,n,1)>=2;}if (tmp==top[tmp]) p=tmp;else p=seq[dfn[tmp]-Query(1,1,n,dfn[top[tmp]],dfn[tmp]).mx[key]+1];modify(fa[x],p,v[x]+1);if (fa[p]) modify(1,1,n,dfn[fa[p]],dfn[fa[p]],Query(1,1,n,dfn[fa[p]])+(key?-1:1));return Query(1,1,n,1)>=2;}}seg;void work(){getseq(); seg.clear(); int q,a;for (read(q);q;--q) read(a),printf("%d\n",seg.modify(a));}int main(){init();work();return 0;}


0 0
原创粉丝点击