noi 2015 软件包管理器(树链剖分)

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

struct my{
  int v;
  int next;
};

const int maxn=200000+10;
my tu[maxn];
int size[maxn];
int tree[maxn<<2];
int lazy[maxn<<2];
int fat[maxn];
char s[20];
int woson[maxn];
int top[maxn],tpos[maxn],last[maxn],d[maxn];
int n;
int dfn;
int tot;
int adj[maxn];

void myinsert(int u,int v){
     tu[++tot].v=v;
     tu[tot].next=adj[u];
     adj[u]=tot;
}

void dfs1(int u,int f){
     size[u]=1;
     for (int i=adj[u];i;i=tu[i].next){
        int v=tu[i].v;
        if(v==f) continue;
        d[v]=d[u]+1;fat[v]=u;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>size[woson[u]]) woson[u]=v;
     }
}

void dfs2(int u,int frist,int fa){
     tpos[u]=++dfn;
     top[u]=frist;
     if(woson[u]) dfs2(woson[u],frist,u);
     for (int i=adj[u];i;i=tu[i].next){
         int v=tu[i].v;
         if(v==fa||v==woson[u]) continue;
         dfs2(v,v,u);
     }
     last[u]=dfn;
}

void pushup(int x){
     tree[x]=tree[x<<1]+tree[x<<1|1];
}

void build(int l,int r,int st){
     if(l==r){
        tree[st]=0;
        return ;
     }
     int mid=(l+r)>>1;
     build(l,mid,st<<1);
     build(mid+1,r,st<<1|1);
}

int read(){
    int x=0;
    char c;
    int tt=1;
    while((c!='-') && c>'9'||c<'0') c=getchar();
    if(c=='-'){
        tt=-1;
        c=getchar();
    }
    while(c<'9'&&c>'0'){
       x=x*10+c-'0';
       c=getchar();
    }
    return x*tt;
}

void pushdown(int x,int ln,int rn){
     if(lazy[x]!=-1){
        lazy[x<<1]=lazy[x];
        lazy[x<<1|1]=lazy[x];
        tree[x<<1]=lazy[x]*ln;
        tree[x<<1|1]=lazy[x]*rn;
        lazy[x]=-1;
     }
}

void change(int l,int r,int st,int L,int R,int c){
     if(L<=l&&r<=R){
        tree[st]=(r-l+1)*c;
        lazy[st]=c;
        return ;
     }
     int mid=(l+r)>>1;
     pushdown(st,mid-l+1,r-mid);
     if(L<=mid) change(l,mid,st<<1,L,R,c);
     if(R>mid) change(mid+1,r,st<<1|1,L,R,c);
     pushup(st);
}

int query(int l,int r,int rt,int L,int R){
    if(L<=l&&r<=R){
        return tree[rt];
    }
    int ans=0;
    int mid=(l+r)>>1;
    pushdown(rt,mid-l+1,r-mid);
    if(L<=mid) ans+=query(l,mid,rt<<1,L,R);
    if(R>mid) ans+=query(mid+1,r,rt<<1|1,L,R);
    return ans;
}

int ask1(int u){
    int v=1;
    int ans=0;
    while(top[u]!=top[v]){
        if(d[top[u]]<d[top[v]]) swap(u,v);
        ans+=query(1,n,1,tpos[top[u]],tpos[u]);
        change(1,n,1,tpos[top[u]],tpos[u],1);
        u=fat[top[u]];
    }
    if(d[u]<d[v]) swap(u,v);
    ans+=query(1,n,1,tpos[v],tpos[u]);
    change(1,n,1,tpos[v],tpos[u],1);
    return ans;
}

int ask2(int x){
    int  ans=query(1, n, 1,tpos[x], last[x]);
            change(1, n, 1, tpos[x], last[x], 0);
            return ans;
}

int main(){
     memset(lazy,-1,sizeof(lazy));
      scanf("%d",&n);
      int u;
      for(int i=2;i<=n;i++){
        scanf("%d",&u);u++;
        myinsert(i,u);
        myinsert(u,i);
      }
      n++;
      d[1]=1;
      fat[1]=1;
      dfs1(1,-1);
      dfs2(1,1,0);
      build(1,n,1);
      int x;
      int q;
      scanf("%d",&q);
     // printf("%d",q);
      while(q--){
          scanf("%s",s);
          scanf("%d",&x);
          x++;
          if(s[0]=='i')
          printf("%d\n",d[x]-ask1(x));
          else printf("%d\n",ask2(x));
      }
  return 0;
}

posted @ 2018-03-04 09:32  lmjer  阅读(135)  评论(0编辑  收藏  举报