NOI 2015 软件包管理器 题解&代码

来源:互联网 发布:淘宝卖什么最好 编辑:程序博客网 时间:2024/06/14 20:01

简单的树链剖分= =不过第一次写真正意义上的树剖坑了我整整五个小时…写出来的代码也不算模板级别的思路,模板还得再找几道题习惯习惯再整理
**对了= =才没有抄过模板呢…在下的模板都是自己根据写法和记忆的难易自己整理出来的

**调了两天,题目已经忘了,等我去整理一下
给出了一颗以0为根节点的Bool类型树,对于一个节点x有两个操作:
1、将该节点到根节点的路径上所有节点值都修改为1
2、将以该节点为根的子树上的节点全部修改为0
对于每次操作,输出这次被修改的节点个数

**需要特别注意的是线段树节点的空间要开四倍…还有要把dfs序号和节点本身的编号分清= =嗯,还有没想好不要乱写
**0号节点开头总归是不好算的,我把编号全部加一了,新的编号下所有节点有一个不存在的父亲0节点

#include<iostream>#include<vector>#include<stdio.h>#define lson (o<<1)#define rson ((o<<1)|1)using namespace std;const int maxn=100005;int n,q,fa[maxn],x,ans,tot;int tree[maxn*4],lazy[maxn*4],pa[maxn],son[maxn],rt[maxn],size[maxn];int in[maxn],out[maxn],deep[maxn];vector <int> edge[maxn];char s[10];int dfs(int r,int d){    deep[r]=d;    size[r]=1;    int z=-1;    for(int i=0;i<edge[r].size();i++)    {        size[r]+=dfs(edge[r][i],d+1);        if(z==-1 || size[edge[r][i]]>size[z])z=edge[r][i];    }    son[r]=z;    return size[r];}void buildtree(int c,int root){    in[c]=++tot;    rt[c]=root;    if(!edge[c].size())    {        out[c]=tot;        return;    }    buildtree(son[c],root);    for(int i=0;i<edge[c].size();i++)        if(edge[c][i]!=son[c])            buildtree(edge[c][i],edge[c][i]);    out[c]=tot;}void pushdown(int o,int l,int r){    if(lazy[o])    {        tree[o]=(r-l+1)*(lazy[o]-1);        if(l!=r)        {            int mid=(l+r)/2;            tree[lson]=(mid-l+1)*(lazy[o]-1);            tree[rson]=(r-mid)*(lazy[o]-1);            lazy[lson]=lazy[rson]=lazy[o];        }    }    lazy[o]=0;}void maintain(int o,int l,int r){    if(l!=r)tree[o]=tree[lson]+tree[rson];}void addtree(int o,int l,int r,int L,int R,int c){    pushdown(o,l,r);    if(l>R || r<L)return;    if(l>=L && r<=R)    {        lazy[o]=c+1;        tree[o]=(r-l+1)*(lazy[o]-1);        return;    }    int mid=(l+r)/2;    addtree(lson,l,mid,L,R,c);    addtree(rson,mid+1,r,L,R,c);    maintain(o,l,r);}void ins(int o,int c){    bool flag=true;    ans=tree[1];    if(c)    {        while(o)        {            addtree(1,1,tot,in[rt[o]],in[o],c);            o=fa[rt[o]];        }        ans=tree[1]-ans;    }    else    {        addtree(1,1,tot,in[o],out[o],c);        ans-=tree[1];    }}int main(void){    scanf("%d",&n);    for(int i=2;i<=n;i++)    {        scanf("%d",&fa[i]);        fa[i]++;        edge[fa[i]].push_back(i);    }    dfs(1,1);    buildtree(1,1);    scanf("%d",&q);    for(int i=1;i<=q;i++)    {        scanf("%s",s);        scanf("%d",&x);        x++;        ans=0;        if(s[0]=='u')        {            ins(x,0);            printf("%d\n",ans);        }        else        {            ins(x,1);            printf("%d\n",ans);        }    }    return 0;}
0 0