题目链接:4196:[Noi2015]软件包管理器
这是一道沙茶题
昨天写一道树链剖分题调了3h最后莫名其妙地过了被人D了一顿
今天我不服我要秒A一道树链剖分给你们看看
然而……
建立线段树的时候写成了这个"p->l;p->r=r;"
然后调了1hQAQ
交了一发E了
又调了0.5h,发现dfs1(int x,int deep)中对儿子进行dfs时写成了dfs1(v,x)QAQ
两个小时才A感觉已经没救了……
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=300010;
int n,m,tot=0,h[maxn],fa[maxn],ind=0,Ans;
struct seg{
int l,r;
int s,data;
seg *lc,*rc;
seg():s(0),data(0){}
};
seg *root=new seg();
struct edge{int to,next;}G[maxn*2];
int s[maxn],pos[maxn],Belong[maxn],dep[maxn];
char str[200];
void add(int x,int y){
G[++tot].to=y;G[tot].next=h[x];h[x]=tot;
}
void dfs1(int x,int deep){
dep[x]=deep; s[x]=1;
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
if (v==fa[x]) continue;
fa[v]=x; dfs1(v,deep+1); s[x]+=s[v];
}
}
void dfs2(int x,int L){
++ind; pos[x]=ind; Belong[x]=L; int k=0;
for (int i=h[x];i;i=G[i].next)
if (dep[G[i].to]>dep[x]&&s[G[i].to]>s[k])
k=G[i].to;
if (!k) return; dfs2(k,L);
for (int i=h[x];i;i=G[i].next)
if (dep[G[i].to]>dep[x]&&G[i].to!=k)
dfs2(G[i].to,G[i].to);
}
void build(seg *p,int l,int r){
p->l=l; p->r=r;
if(l+1==r){p->s=0;p->lc=p->rc=NULL;return;}
else if (l+1<r){
int mid=(l+r)>>1;
p->lc=new seg();
p->rc=new seg();
if (l<mid) build(p->lc,l,mid);
else p->lc=NULL;
if (mid<r) build(p->rc,mid,r);
else p->rc=NULL;
}
}
void push_down(seg *p){
if (p->l+1==p->r) return;
if (p->data==1){
if (p->lc!=NULL) p->lc->s=p->lc->r - p->lc->l,p->lc->data=1;
if (p->rc!=NULL) p->rc->s=p->rc->r - p->rc->l,p->rc->data=1;
}else if (p->data==2){
if (p->lc!=NULL) p->lc->s=0,p->lc->data=2;
if (p->rc!=NULL) p->rc->s=0,p->rc->data=2;
}p->data=0;
}
void ask1(seg *p,int l,int r){
if (l<=p->l&&p->r<=r){Ans+=p->s;return;}
push_down(p);
int mid=(p->l+p->r)>>1;
if (l<mid) ask1(p->lc,l,r);
if (mid<r) ask1(p->rc,l,r);
}
void ask0(seg *p,int l,int r){
if (l<=p->l&&p->r<=r){Ans+=(p->r-p->l)-p->s;return;}
push_down(p);
int mid=(p->l+p->r)>>1;
if (l<mid) ask0(p->lc,l,r);
if (mid<r) ask0(p->rc,l,r);
}
void push_up(seg *p){
if (p->l+1==p->r) return;
p->s=0;
if (p->lc) p->s+=p->lc->s;
if (p->rc) p->s+=p->rc->s;
}
void change(seg *p,int l,int r,bool flag){
if(l<=p->l&&p->r<=r)
if(flag==1){p->s=p->r-p->l;p->data=1;return;}
else{p->s=0;p->data=2;return;}
push_down(p);
int mid=(p->l+p->r)>>1;
if (l<mid) change(p->lc,l,r,flag);
if (mid<r) change(p->rc,l,r,flag);
push_up(p);
}
int query1(int x,int y){
int sum=0;
while (Belong[x]!=Belong[y]){
if (dep[Belong[x]]<dep[Belong[y]]) swap(x,y);
Ans=0; ask1(root,pos[Belong[x]],pos[x]+1);
sum+=Ans; x=fa[Belong[x]];
}
if (dep[x]<dep[y]) swap(x,y);
Ans=0; ask1(root,pos[y],pos[x]+1);
sum+=Ans; return sum;
}
int query0(int x,int y){
int sum=0;
while (Belong[x]!=Belong[y]){
if (dep[Belong[x]]<dep[Belong[y]]) swap(x,y);
Ans=0; ask0(root,pos[Belong[x]],pos[x]+1);
sum+=Ans; x=fa[Belong[x]];
}
if (dep[x]<dep[y]) swap(x,y);
Ans=0; ask0(root,pos[y],pos[x]+1);
sum+=Ans; return sum;
}
void changel(int x,int y){
while (Belong[x]!=Belong[y]){
if (dep[Belong[x]]<dep[Belong[y]]) swap(x,y);
change(root,pos[Belong[x]],pos[x]+1,1);
x=fa[Belong[x]];
}
if (dep[x]<dep[y]) swap(x,y);
change(root,pos[y],pos[x]+1,1);
}
void work1(){
int x; scanf("%d",&x); x++;
printf("%d\n",query0(x,1));
changel(x,1);
}
void work2(){
int x; scanf("%d",&x); x++;
Ans=0; ask1(root,pos[x],pos[x]+s[x]);
printf("%d\n",Ans);
change(root,pos[x],pos[x]+s[x],0);
}
int main(){
scanf("%d",&n);
for (int i=1;i<n;++i){
int x; scanf("%d",&x); x++;
add(x,i+1);
}
dfs1(1,0); dfs2(1,1);
build(root,1,n+1);
scanf("%d",&m);
for (int i=1;i<=m;++i){
scanf("%s",str);
if (str[0]=='i') work1();
else work2();
}
}