【NOI2015】软件包管理器(树链剖分)

来源:互联网 发布:c语言map容器 编辑:程序博客网 时间:2024/06/07 15:10

https://loj.ac/problem/2130

显然这道题是一个树状结构。
对于两种操作
设未安装为0,已安装为1
install x,相当于查询从0到x的路径中有多少个0,再将路径中的所有值置为1
uninstall x,相当于查询x的子树中有多少个1,再将子树中的所有值置为0

其实就是模板题,为了方便实现,我将0和1互换,这样的话install过程直接区间求和与区间修改。
而uninstall过程子树求和后再用子树的大小减去求得和,得到子树中0的个数。修改直接修改子树即可。

#include<bits/stdc++.h>#define fer(i,j,n) for(int i=j;i<=n;i++)#define far(i,j,n) for(int i=j;i>=n;i--)#define ll long long#define pa pair<int,int>const int maxn=1000010;const int INF=1e9+7;using namespace std;/*----------------------------------------------------------------------------*/inline ll read(){    char ls;ll x=0,sng=1;    for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;    for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';    return x*sng;}/*----------------------------------------------------------------------------*/ll n,m; struct kaga{    int next;    int point;}e[maxn];struct akagi{    int l,r;    ll sum,lazy;}tr[maxn];int last[maxn],k=0,fa[maxn],size[maxn],son[maxn],belong[maxn],hashh[maxn],hashv[maxn],dep[maxn],v[maxn];void sumup(int x){    tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;    return ;}void pushdown(int x){    int y=tr[x].lazy;    if(y==1)    {        tr[x<<1].lazy=1;        tr[x<<1].sum=(tr[x<<1].r-tr[x<<1].l+1);        tr[x<<1|1].lazy=1;        tr[x<<1|1].sum=(tr[x<<1|1].r-tr[x<<1|1].l+1);       }    if(y==2)    {        tr[x<<1].lazy=2;        tr[x<<1].sum=0;        tr[x<<1|1].lazy=2;        tr[x<<1|1].sum=0;       }    tr[x].lazy=0;}void build(int x,int l,int r){    int mid=(l+r)>>1;    tr[x].l=l;tr[x].r=r;    if(l==r)    {        tr[x].sum=1;        tr[x].lazy=0;        return ;    }    build(x<<1,l,mid);    build(x<<1|1,mid+1,r);    sumup(x);    return ;}void change(int x,int L,int R,int val){    int l=tr[x].l,r=tr[x].r,mid=(l+r)>>1;    if(L<=l&&r<=R)    {        if(val==1)        {            tr[x].sum=r-l+1;            tr[x].lazy=1;           }        else        if(val==2)        {            tr[x].sum=0;            tr[x].lazy=2;           }        return ;    }    pushdown(x);    if(R<=mid)change(x<<1,L,R,val);    else if(L>mid)change(x<<1|1,L,R,val);    else change(x<<1,L,mid,val),change(x<<1|1,mid+1,R,val);    sumup(x);    return ;}ll query(int x,int L,int R){    int l=tr[x].l,r=tr[x].r,mid=(l+r)>>1;    if(L<=l&&r<=R)return tr[x].sum;    pushdown(x);    if(R<=mid)query(x<<1,L,R);    else if(L>mid)query(x<<1|1,L,R);    else return query(x<<1,L,mid)+query(x<<1|1,mid+1,R);}void add_edge(int x,int y){    e[++k].next=y;e[k].point=last[x];last[x]=k;}void insert(int x,int y){    add_edge(x,y);    add_edge(y,x);}void dfs1(int x,int fat){    fa[x]=fat;    dep[x]=dep[fat]+1;    size[x]=1;    for(int j=last[x];j;j=e[j].point)    {        int y=e[j].next;        if(y==fat)continue;        dfs1(y,x);        size[x]+=size[y];        if(!son[x]||size[y]>size[son[x]])        son[x]=y;       }}void dfs2(int x,int top){    belong[x]=top;    hashh[x]=++k;    hashv[k]=x;    if(!son[x])return ;    dfs2(son[x],top);    for(int j=last[x];j;j=e[j].point)    {        int y=e[j].next;        if(y!=son[x]&&y!=fa[x])        dfs2(y,y);      }}void update(int x,int y,int val){    int topx=belong[x];    int topy=belong[y];    while(topx!=topy)    {        if(dep[topx]<dep[topy])        {            swap(x,y);            swap(topx,topy);            }        change(1,hashh[topx],hashh[x],val);        x=fa[topx];        topx=belong[x];    }    if(dep[x]>dep[y])swap(x,y);    change(1,hashh[x],hashh[y],val);}ll sigma(int x,int y){    ll sum=0;    int topx=belong[x];    int topy=belong[y];    while(topx!=topy)    {        if(dep[topx]<dep[topy])        {            swap(x,y);            swap(topx,topy);            }        sum+=query(1,hashh[topx],hashh[x]);        x=fa[topx];        topx=belong[x];    }    if(dep[x]>dep[y])swap(x,y);    sum+=query(1,hashh[x],hashh[y]);    return sum;}void updateson(int x,int val){    int left=hashh[x];    int right=hashh[x]+size[x]-1;    change(1,left,right,val);}ll sigmason(int x){    int left=hashh[x];    int right=hashh[x]+size[x]-1;    return right-left+1-query(1,left,right);}int main(){    n=read();    fer(i,2,n)    {        int x=read()+1;        insert(x,i);    }    k=0;    dfs1(1,0);    dfs2(1,1);    build(1,1,n);    m=read();    fer(i,1,m)    {        char ls[10];        scanf("%s",ls);        if(ls[0]=='i')        {            int x=read()+1;            cout<<sigma(1,x)<<endl;            update(1,x,2);        }        else        {            int x=read()+1;            cout<<sigmason(x)<<endl;            updateson(x,1);        }    }} 
阅读全文
0 0