离线后 树链剖分||树状数组。
在第day天查询危险值>c的人的个数,也就是查询第(day-c-1)天及以前开始收集情报的人的个数。
所以离线后按时间排一下序。。就变成了单点修改,查询路径上已被修改的点的个数。
注意一个人可能多次开始收集情报。。一开始没注意挂了一发
突然发现。。这样的话我们直接上树状数组就行了QAQ。。。反正dfs序什么的都搞好了。
我果然是傻逼TAT
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=200233; 7 struct ask{ 8 int x,y,id,pos,day; 9 }q[maxn]; 10 struct zs{ 11 int too,pre; 12 }e[maxn];int tot,last[maxn]; 13 int lc[maxn<<1],rc[maxn<<1],sm[maxn<<1],tt; 14 int dfn[maxn],top[maxn],fa[maxn],sz[maxn],dep[maxn],tim; 15 int ans1[maxn],ans2[maxn]; 16 int i,j,k,n,m,x,y,lca,rt; 17 bool u[maxn]; 18 19 int ra;char rx; 20 inline int read(){ 21 rx=getchar(),ra=0; 22 while(rx<'0'||rx>'9')rx=getchar(); 23 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 24 } 25 26 inline void insert(int a,int b){ 27 e[++tot].too=b,e[tot].pre=last[a],last[a]=tot; 28 } 29 inline void dfs1(int x){ 30 sz[x]=1,dep[x]=dep[fa[x]]+1; 31 for(int i=last[x];i;i=e[i].pre) 32 dfs1(e[i].too),sz[x]+=sz[e[i].too]; 33 } 34 inline void dfs2(int x,int chain){ 35 dfn[x]=++tim,top[x]=chain;int i,mx=0;//printf(" %d %d %d ",x,dfn[x],top[x]); 36 for(i=last[x];i;i=e[i].pre)if(sz[e[i].too]>sz[mx])mx=e[i].too; 37 if(!mx)return; 38 dfs2(mx,chain); 39 for(i=last[x];i;i=e[i].pre)if(e[i].too!=mx)dfs2(e[i].too,e[i].too); 40 } 41 inline int getlca(int a,int b){ 42 while(top[a]!=top[b]){ 43 if(dep[top[a]]<dep[top[b]])swap(a,b); 44 a=fa[top[a]]; 45 } 46 return dep[a]<dep[b]?a:b; 47 } 48 49 inline void build(int a,int b){ 50 tt++;if(a==b)return; 51 int x=tt,mid=(a+b)>>1; 52 lc[x]=tt+1,build(a,mid),rc[x]=tt+1,build(mid+1,b); 53 } 54 inline void add(int x,int a,int b,int pos){ 55 int mid;//printf("add %d ",pos); 56 while(a<b){ 57 mid=(a+b)>>1,sm[x]++;//printf("add %d ",x); 58 if(pos<=mid)x=lc[x],b=mid;else x=rc[x],a=mid+1; 59 } 60 sm[x]++;//printf(" ! %d ",sm[1]); 61 } 62 inline int query(int x,int a,int b,int l,int r){ 63 if(l<=a&&r>=b)return sm[x]; 64 int mid=(a+b)>>1; 65 if(r<=mid)return query(lc[x],a,mid,l,r);else 66 if(l>mid)return query(rc[x],mid+1,b,l,r);else 67 return query(lc[x],a,mid,l,r)+query(rc[x],mid+1,b,l,r); 68 } 69 70 inline int QUERY(int a,int b){ 71 int sum=0;//printf("QUERY:%d %d",a,b); 72 while(top[a]!=top[b]){ 73 sum+=query(1,1,n,dfn[top[a]],dfn[a]);//printf(" %d--%d %d ",top[a],a,sum); 74 a=fa[top[a]]; 75 } 76 sum+=query(1,1,n,dfn[b],dfn[a]);//printf(" %d ",sum); 77 return sum; 78 } 79 80 bool cmp(ask a,ask b){return a.day==b.day?a.id==2:a.day<b.day;} 81 int main(){ 82 n=read(); 83 for(i=1;i<=n;i++){ 84 fa[i]=read();if(fa[i])insert(fa[i],i);else rt=i; 85 } 86 dfs1(rt),dfs2(rt,rt); 87 build(1,n); 88 m=read(); 89 for(i=1;i<=m;i++){ 90 q[i].id=read();q[i].pos=i; 91 if(q[i].id==1)q[i].x=read(),q[i].y=read(),q[i].day=i-read()-1; 92 else q[i].x=read(),q[i].day=i; 93 } 94 sort(q+1,q+1+m,cmp); 95 // for(i=1;i<=m;i++)printf(" %d %d ",q[i].id,q[i].day); 96 memset(ans2,255,sizeof(ans2)); 97 for(i=1;i<=m;i++) 98 if(q[i].id==2){ 99 if(!u[q[i].x]) 100 add(1,1,n,dfn[q[i].x]),u[q[i].x]=1; 101 }else{ 102 lca=getlca(q[i].x,q[i].y);//printf("%d %d lca:%d ",q[i].x,q[i].y,lca); 103 int sum=QUERY(q[i].x,lca)+QUERY(q[i].y,lca)-query(1,1,n,dfn[lca],dfn[lca]); 104 ans1[q[i].pos]=dep[q[i].x]+dep[q[i].y]-dep[lca]*2+1;ans2[q[i].pos]=sum; 105 } 106 for(i=1;i<=m;i++)if(ans2[i]!=-1)printf("%d %d ",ans1[i],ans2[i]); 107 return 0; 108 }