[bzoj4448] [Scoi2015]情报传递

  离线后  树链剖分||树状数组。

  在第day天查询危险值>c的人的个数,也就是查询第(day-c-1)天及以前开始收集情报的人的个数。

  所以离线后按时间排一下序。。就变成了单点修改,查询路径上已被修改的点的个数。

  注意一个人可能多次开始收集情报。。一开始没注意挂了一发

 

  突然发现。。这样的话我们直接上树状数组就行了QAQ。。。反正dfs序什么的都搞好了。

我果然是傻逼TAT

  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\n",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\n",pos);
 56     while(a<b){
 57         mid=(a+b)>>1,sm[x]++;//printf("add       %d\n",x);
 58         if(pos<=mid)x=lc[x],b=mid;else x=rc[x],a=mid+1;
 59     }
 60     sm[x]++;//printf("  ! %d\n",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\n",top[a],a,sum);
 74         a=fa[top[a]];
 75     }
 76     sum+=query(1,1,n,dfn[b],dfn[a]);//printf(" %d\n",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\n",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\n",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\n",ans1[i],ans2[i]);
107     return 0;
108 }
View Code

 

posted @ 2016-03-22 22:03  czllgzmzl  阅读(253)  评论(0编辑  收藏  举报