【bzoj4196】[NOI2015]软件包管理器

来源:互联网 发布:mac adb 导出文件 编辑:程序博客网 时间:2024/06/09 08:14

树剖
完全没有对链的操作,维护一个dfs序就好
这个题调了1个多小时,树链剖分写丑了。。。
要注意树剖的线段树维护的是dfs序,所以起止是1 - n而不是0 - n-1
其实也是因为从来把1当作根结点,所以偶尔把0当作根结点就容易写丑了,平常的练习还是要培养自己的码风,这样有助于比赛的时候正常的发挥.

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>//树剖的线段树维护的是dfs序,所以起止是1 - n而不是0 - n-1 using namespace std;const int N=100010;int n,m,sz,qx,te;char s[15];int head[N],num[N],son[N],fa[N],tp[N],size[N];struct edge{    int u,v,next;}e[200020];struct seg{    int l,r;    int numi,numu,tag;}tr[600010];inline int F(){    register int aa,bb;register char ch;    while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);    while(ch=getchar(),ch>='0'&&ch<='9')aa=(aa<<3)+(aa<<1)+ch-'0';return bb?aa:-aa;}void add(int u,int v){    e[++te].u=u;    e[te].v=v;    e[te].next=head[u];    head[u]=te;}void dfs1(int x){    size[x]=1;    int maxson=0;    for (int i=head[x];i;i=e[i].next)    {        int v=e[i].v;        if (v==fa[x])continue;        fa[v]=x;        dfs1(v);        size[x]+=size[v];        if (size[v]>maxson)son[x]=v,maxson=size[v];    }}void dfs2(int x,int chain){    tp[x]=chain;    num[x]=++sz;    if(son[x]==-1)return;    dfs2(son[x],chain);    for (int i=head[x];i;i=e[i].next)    {        int v=e[i].v;        if (v==fa[x]||v==son[x])continue;        dfs2(v,v);    } }void pushdown(int k){    int l=tr[k].l,r=tr[k].r;    if (tr[k].tag==-1||l==r)return;    int mid=(l+r)>>1;    tr[k<<1].tag=tr[k<<1|1].tag=tr[k].tag;    if (tr[k].tag==0)    {        tr[k<<1].numu=mid-l+1;        tr[k<<1|1].numu=r-mid;        tr[k<<1].numi=tr[k<<1|1].numi=0;    }    else     {        tr[k<<1].numi=mid-l+1;        tr[k<<1|1].numi=r-mid;        tr[k<<1].numu=tr[k<<1|1].numu=0;    }    tr[k].tag=-1;}void updata(int k){    tr[k].numi=tr[k<<1].numi+tr[k<<1|1].numi;    tr[k].numu=tr[k<<1].numu+tr[k<<1|1].numu;}void build(int k,int l,int r){    tr[k].l=l,tr[k].r=r,tr[k].tag=-1;    if (l==r)    {        tr[k].numi=0;        tr[k].numu=1;        return;     }    int mid=(l+r)>>1;    build(k<<1,l,mid);    build(k<<1|1,mid+1,r);    updata(k);}void change(int k,int x,int y,int z){//  cout<<tr[k].l<<' '<<tr[k].r<<' '<<tr[k].numi<<' '<<tr[k].numu<<' '<<x<<' '<<y<<endl;    int l=tr[k].l,r=tr[k].r;    if (x<=l&&r<=y)    {        tr[k].tag=z;        if (z)        {            qx+=tr[k].numu;            tr[k].numi=r-l+1;            tr[k].numu=0;        }        else         {            qx+=tr[k].numi;            tr[k].numu=r-l+1;            tr[k].numi=0;        }        return;    }    pushdown(k);    int mid=(l+r)>>1;    if (x<=mid)change(k<<1,x,y,z);    if (y>mid)change(k<<1|1,x,y,z);    updata(k);}void query(int x){    while(tp[x]!=0)    {        change(1,num[tp[x]],num[x],1);        x=fa[tp[x]];     }    change(1,num[tp[x]],num[x],1);    return ;}int main(){//  freopen("std.in","r",stdin);    memset(son,-1,sizeof(son));    int x,u,v;    n=F();    for (int i=1;i<n;++i)    v=F(),add(v,i);    fa[0]=0;    dfs1(0);dfs2(0,0);build(1,1,n);    m=F();    for (int i=1;i<=m;++i)    {//      cout<<endl<<endl<<endl<<endl<<endl;        scanf("%s",s);        x=F();qx=0;         if (s[0]=='i')query(x);        else change(1,num[x],num[x]+size[x]-1,0);        printf("%d\n",qx);    }    return 0;} 
0 0
原创粉丝点击