[NOI2015] 软件包管理器

link

试题分析

 数据结构板子题。其中只需要维护区间覆盖,区间查询的线段树。而这是在一棵树中,所以考虑树链剖分。

然后就真是板子了。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int N=200001;
struct node{
    int u,v,nex;
}x[N<<1];
int cnt,head[N],n,deep[N],seg[N],rev[N],top[N],son[N],size[N],father[N];
void dfs1(int f,int fath){
    size[f]=1;
    father[f]=fath;
    deep[f]=deep[fath]+1;
    for(int i=head[f];i!=-1;i=x[i].nex){
        if(x[i].v==fath) continue;
        dfs1(x[i].v,f);
        size[f]+=size[x[i].v];
        if(son[f]==-1){son[f]=x[i].v;}
        else if(size[x[i].v]>size[son[f]]) son[f]=x[i].v;
    }
    return;
}
void dfs2(int f,int fath){
    if(son[f]!=-1){
        seg[son[f]]=++seg[0];
        rev[seg[0]]=son[f];
        top[son[f]]=top[f];
        dfs2(son[f],f);
    }
    for(int i=head[f];i!=-1;i=x[i].nex){
        if(x[i].v==fath||son[f]==x[i].v) continue;
        seg[x[i].v]=++seg[0];
        rev[seg[0]]=x[i].v;
        top[x[i].v]=x[i].v;
        dfs2(x[i].v,f);
    }
}
void add(int u,int v){
    x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++;
}int q;
char str[21];
int flag[N<<1],ans[N<<1];
void pushdown(int k,int l,int r){
    if(flag[k]==-1) return;
    int mid=l+r>>1;
    flag[k<<1]=flag[k<<1|1]=flag[k];
    ans[k<<1]=(mid-l+1)*flag[k<<1];
    ans[k<<1|1]=(r-mid)*flag[k<<1|1];
    flag[k]=-1;
    return;
}
int query(int k,int l,int r,int x,int y){
    if(x<=l&&r<=y) return ans[k];
    pushdown(k,l,r);
    int mid=l+r>>1,res=0;
    if(x<=mid) res+=query(k<<1,l,mid,x,y);
    if(mid<y) res+=query(k<<1|1,mid+1,r,x,y);
    ans[k]=ans[k<<1]+ans[k<<1|1];
    return res; 
}
int ask_sum(int x,int y){
    int fx=top[x],fy=top[y],res=0;
    while(fx!=fy){
        if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy);
        res+=query(1,1,seg[0],seg[fx],seg[x]);
        x=father[fx];fx=top[x];
    }
    if(deep[x]>deep[y]) swap(x,y);
    res+=query(1,1,seg[0],seg[x],seg[y]);
    return res;
}
void update(int k,int l,int r,int x,int y,int w){
    if(x<=l&&r<=y){
        flag[k]=w;
        ans[k]=(r-l+1)*flag[k];
        return;
    }
    pushdown(k,l,r);
    int mid=l+r>>1;
    if(x<=mid) update(k<<1,l,mid,x,y,w);
    if(mid<y) update(k<<1|1,mid+1,r,x,y,w);
    ans[k]=ans[k<<1]+ans[k<<1|1];
    return;
}
void change(int x,int y,int w){
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(deep[fx]<deep[fy]) swap(x,y),swap(fx,fy);
        update(1,1,seg[0],seg[fx],seg[x],w);
        x=father[fx],fx=top[x];
    }
    if(deep[x]>deep[y]) swap(x,y);
    update(1,1,seg[0],seg[x],seg[y],w);
    return;
}
int main(){
//    freopen("1.in","r",stdin);
    memset(son,-1,sizeof(son));
    memset(flag,-1,sizeof(flag));
    memset(head,-1,sizeof(head));
    n=read();
    for(int i=2;i<=n;i++){
        int v=read();v++;
        add(i,v),add(v,i);
    }
    dfs1(1,0);    
    seg[1]=seg[0]=rev[1]=top[1]=1;
    dfs2(1,0);
    q=read();
    while(q--){
        scanf("%s",str+1);
        if(str[1]=='i'){
            int x=read();
            x++;
            int Ask=ask_sum(1,x);
            printf("%d\n",deep[x]-Ask);
            change(1,x,1);
        }
        if(str[1]=='u'){
            int x=read();
            x++;
            int sum=query(1,1,seg[0],seg[x],seg[x]+size[x]-1);
            printf("%d\n",sum);
            update(1,1,seg[0],seg[x],seg[x]+size[x]-1,0);
        }
    }
    return 0;
}
View Code

 

posted @ 2018-12-20 13:10  siruiyang_sry  阅读(136)  评论(0编辑  收藏  举报