[BZOJ] 4196 [Noi2015]软件包管理器

安装操作就是链上统计+更改,卸载操作就是子树统计+更改,没有比树剖更合适的了。
数组开小会莫名WA..qwq

#include<iostream>
#include<cstdio>

using namespace std;

const int MAXN=1000005;

int n,m;

#define ls (cur<<1)
#define rs ((cur<<1)+1)
#define mid ((l+r)>>1)
int sum[MAXN],lazy[MAXN];
void pushup(int cur){sum[cur]=sum[ls]+sum[rs];}
void pushdown(int cur,int l,int r){
  sum[ls]=(lazy[cur])*(mid-l+1);
  sum[rs]=(lazy[cur])*(r-mid);
  lazy[ls]=lazy[rs]=lazy[cur];
  lazy[cur]=-1;
} 
void build(int cur,int l,int r){
  if(l==r){sum[cur]=0;return;}
  build(ls,l,mid);build(rs,mid+1,r);
  lazy[cur]=-1;
  pushup(cur);
}
void updata(int L,int R,int cur,int l,int r,int w){
  if(L<=l&&r<=R){sum[cur]=w*(r-l+1);lazy[cur]=w;return;}
  if(lazy[cur]!=-1) pushdown(cur,l,r);
  if(L<=mid) updata(L,R,ls,l,mid,w);
  if(mid <R) updata(L,R,rs,mid+1,r,w);
  pushup(cur);
}
int query(int L,int R,int cur,int l,int r){
  if(L<=l&&r<=R) return sum[cur];
  if(lazy[cur]!=-1) pushdown(cur,l,r);
  int ret=0;
  if(L<=mid) ret+=query(L,R,ls,l,mid);
  if(mid <R) ret+=query(L,R,rs,mid+1,r);
  return ret;
}
int query0(int L,int R,int cur,int l,int r){
  if(L<=l&&r<=R) return r-l+1-sum[cur];
  if(lazy[cur]!=-1) pushdown(cur,l,r);
  int ret=0;
  if(L<=mid) ret+=query0(L,R,ls,l,mid);
  if(mid <R) ret+=query0(L,R,rs,mid+1,r);
  return ret;
}
struct Edge{
  int next,to;
}e[MAXN<<1];
int ecnt,head[MAXN];
inline void add(int x,int y){
  e[++ecnt].to = y;
  e[ecnt].next = head[x];
  head[x] = ecnt;
}
int dep[MAXN],fa[MAXN],hs[MAXN],siz[MAXN];
void dfs1(int cur,int pre){
  fa[cur]=pre;dep[cur]=dep[pre]+1;siz[cur]=1;
  int mx=-1;
  for(int i=head[cur];i;i=e[i].next){
    int v=e[i].to;
    if(v==pre) continue;
    dfs1(v,cur);
    siz[cur]+=siz[v];
    if(siz[v]>mx) mx=siz[v],hs[cur]=v;
  }
}
int top[MAXN],id[MAXN],cnt;
void dfs2(int cur,int tp){
  id[cur]=++cnt;top[cur]=tp;
  if(hs[cur]) dfs2(hs[cur],tp);
  for(int i=head[cur];i;i=e[i].next){
    int v=e[i].to;
    if(v==fa[cur]||v==hs[cur]) continue;
    dfs2(v,v);
  }
}
int query_link(int x,int y){
  int ret=0;
  while(top[x]!=top[y]){
    if(dep[top[x]]<dep[top[y]]) swap(x,y);
    ret+=query0(id[top[x]],id[x],1,1,n);
    x=fa[top[x]];
  }
  if(dep[x]>dep[y]) swap(x,y);
  ret+=query0(id[x],id[y],1,1,n);
  return ret;
}
void updata_link(int x,int y,int w){
  while(top[x]!=top[y]){
    if(dep[top[x]]<dep[top[y]]) swap(x,y);
    updata(id[top[x]],id[x],1,1,n,w);
    x=fa[top[x]];
  }
  if(dep[x]>dep[y]) swap(x,y);
  updata(id[x],id[y],1,1,n,w);
}
int query_subtree(int x){
  return query(id[x],id[x]+siz[x]-1,1,1,n);
}
void updata_subtree(int x,int w){
  updata(id[x],id[x]+siz[x]-1,1,1,n,w);
}

int main(){
  scanf("%d",&n);
  int x;
  for(int i=2;i<=n;i++) {
    scanf("%d",&x);
    x++;
    add(i,x);add(x,i);
  }
  dfs1(1,0);
  dfs2(1,1);
  build(1,1,n);
  scanf("%d",&m);
  char s[500];
  for(int i=1;i<=m;i++){
    scanf("%s%d",s,&x);
    x++;
    if(s[0]=='i'){
      printf("%d\n",query_link(1,x));
      updata_link(1,x,1);
    }else{
      printf("%d\n",query_subtree(x));
      updata_subtree(x,0);
    }
  }

  return 0;
}
posted @ 2018-06-24 11:57  GhostCai  阅读(111)  评论(0编辑  收藏  举报