bzoj 4448: [Scoi2015]情报传递

Posted CXCXCXC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4448: [Scoi2015]情报传递相关的知识,希望对你有一定的参考价值。

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 117  Solved: 65
[Submit][Status][Discuss]

Description

奈特公司是一个巨大的情报公司,它有着庞大的情报网络。情报网络中共有n名情报员。每名情报员口J-能有若T名(可能没有)下线,除1名大头日外其余n-1名情报员有且仅有1名上线。奈特公司纪律森严,每名情报员只能与自己的上、下线联系,同时,情报网络中仟意两名情报员一定能够通过情报网络传递报。
奈特公司每天会派发以下两种任务中的一个任务:
1.搜集情报:指派T号情报员搜集情报
2.传递情报:将一条情报从X号情报员传递给Y号情报员
情报员最初处于潜伏阶段,他们是相对安全的,我们认为此时所有情报员的危险值为0;-旦某个情报员开始搜集情报,他的危险值就会持续增加,每天增加1点危险值(开始搜集情报的当天危险值仍为0,第2天危险值为1,第3天危险值为2,以此类推)。传递情报并不会使情报员的危险值增加。为了保证传递情报的过程相对安全,每条情报都有一个风险控制值C。余特公司认为,参与传递这条情报的所有情报员中,危险值大于C的情报员将对该条情报构成威胁。现在,奈特公司希望知道,对于每个传递情报任务,参与传递的情报员有多少个,其中对该条情报构成威胁的情报员有多少个。

Input

第1行包含1个正整数n,表示情报员个数。
笫2行包含n个非负整数,其中第i个整数Pi表示i号情报员上线的编号。特别地,若Pi=0,表示i号情报员是大头目。
第3行包含1个正整数q,表示奈特公司将派发q个任务(每天一个)。
随后q行,依次描述q个任务。
每行首先有1个正整数k。若k=1,表示任务是传递情报,随后有3个正整数Xi、Yi、Ci,依次表示传递情报的起点、终点和风险控制值;若k=2,表示任务是搜集情报,随后有1个正整数Ti,表示搜集情报的情报员编号。

Output

对于每个传递情报任务输出一行,应包含两个整数,分别是参与传递情报的情报员个数和对该条情报构成威胁的情报员个数。输出的行数应等于传递情报任务的个数,每行仅包含两个整数,用一个空格隔开。输出不应包含多余的空行和空格。

Sample Input

7
0 1 1 2 2 3 3
6
1 4 7 0
2 1
2 4
2 7
1 4 7 1
1 4 7 3

Sample Output

5 0
5 2
5 1

HINT

对于3个传递情报任务,都是经过5名情报员,分别是4号、2号、1号、3号和7号。其中,对于第1个任务,所有情报员(危险值为0)都不对情报构成威胁;对于第2个任务,有2名情报员对情报构成威胁,分别是1号情报员(危险值为3)和4号情报员(危险值为2),7号情报员(危险值为1)并不构成威胁;
对于第3个任务,只有1名情报员对情报构成威胁。
n< = 2×10^5,Q< = 2×105,0< Pi,C!< = N, 1< = Ti,Xi,Yi< = n
 
题解:
  可以发现情报人员之间的关系可以转化成一棵树,问题转化成了在某一时刻把树上的某一点染色成黑点, 然后在某一时刻T,询问u~v的链中,有多少个点和在T-C-1及之前染色成黑色的点的个数。
  对于第一个询问可以直接LCA来求,设每条边的边权为1,sum[i][j],表示i到i的2^j倍祖先的距离,再此基础上+1就是第一个询问的ans。对于第二个询问,可以用树链剖分+离线操作。对于询问,设时间tim为T-C-1,,对于染色,tim为i。
  1 /**************************************************************
  2     Problem: 4448
  3     User: __abcdef__
  4     Language: C++
  5     Result: Accepted
  6     Time:6916 ms
  7     Memory:90304 kb
  8 ****************************************************************/
  9  
 10 #include<iostream>
 11 #include<cstdio>
 12 #include<cstdlib>
 13 #include<cstring>
 14 #include<cmath>
 15 #include<algorithm>
 16 #include<queue>
 17 #include<vector>
 18 using namespace std;
 19 typedef long long LL;
 20 const int inf=1e9;
 21 const int maxn=2*1e5+5;
 22 int N,Q;
 23 int dep[maxn],fa[maxn],p[maxn][32],sum[maxn][32],ANS[maxn];
 24 vector<int> son[maxn],now;
 25 struct questi{
 26     int kin,from,to,c;
 27     int num;
 28     int id,ans1,ans2;
 29     int tim;
 30 }q[maxn];
 31 inline bool cmp1(const questi & a,const questi & b){
 32     return a.tim<b.tim||(a.tim==b.tim&&a.kin>b.kin);
 33 }
 34 inline bool cmp2(const questi & a,const questi & b){
 35     return a.id<b.id;
 36 }
 37 inline void dfs(int rt){
 38     for(int i=0;i<(int)son[rt].size();i++){
 39         int y=son[rt][i];
 40         dep[y]=dep[rt]+1;
 41         p[y][0]=rt; sum[y][0]=1;
 42         for(int k=1;k<=30;k++){
 43             int zu=1<<k;
 44             if(zu<=dep[y]){
 45                 p[y][k]=p[p[y][k-1]][k-1];
 46                 sum[y][k]=sum[y][k-1]+sum[p[y][k-1]][k-1];
 47             }
 48             else break;
 49         }
 50         dfs(y);
 51     }
 52 }
 53 inline int LCA(int x,int y){
 54     int ans=0;
 55     if(dep[x]>dep[y]) swap(x,y);
 56     int delta=dep[y]-dep[x];
 57     for(int i=0;i<=30;i++){
 58         int h=(1<<i); h=(h&delta);
 59         if(h!=0){
 60             ans+=sum[y][i];
 61             y=p[y][i];
 62         }
 63     }
 64     if(x==y) return ans;
 65     for(int i=30;i>=0;i--){
 66         if(p[y][i]!=p[x][i]){
 67             ans+=(sum[y][i]+sum[x][i]);
 68             y=p[y][i]; x=p[x][i];
 69         }
 70     }
 71     ans+=sum[y][0]; ans+=sum[x][0];
 72     return ans;
 73 }
 74 int dep2[maxn],siz[maxn],Son[maxn],id[maxn],top[maxn],tot;
 75 inline void dfs1(int rt,int fath,int deep){
 76     dep2[rt]=deep; siz[rt]=1; Son[rt]=0;
 77     for(int i=0;i<(int)son[rt].size();i++){
 78         int y=son[rt][i];
 79         dfs1(y,rt,deep+1);
 80         siz[rt]+=siz[y];
 81         if(siz[y]>siz[Son[rt]]){
 82             Son[rt]=y;
 83         }
 84     }
 85 }
 86 inline void dfs2(int rt,int tp){
 87     top[rt]=tp; id[rt]=++tot;
 88     if(Son[rt]!=0) dfs2(Son[rt],tp);
 89     for(int i=0;i<(int)son[rt].size();i++){
 90         int y=son[rt][i];
 91         if(y!=Son[rt]) dfs2(y,y);
 92     }
 93 }
 94 struct Tree{
 95     int l,r;
 96     int sum;
 97 }T[maxn*8];
 98 inline void build(int rt,int l,int r){
 99     T[rt].l=l; T[rt].r=r;
100     if(l==r){
101         T[rt].sum=0;
102         return ;
103     }
104     int mid=(l+r)>>1;
105     build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);
106     T[rt].sum=T[rt<<1].sum+T[rt<<1|1].sum;
107 }
108 inline void change(int rt,int pos,int v){
109     if(T[rt].l==T[rt].r){
110         T[rt].sum=v;
111         return ;
112     }
113     int mid=(T[rt].l+T[rt].r)>>1;
114     if(pos<=mid) change(rt<<1,pos,v);
115     else change(rt<<1|1,pos,v);
116     T[rt].sum=T[rt<<1].sum+T[rt<<1|1].sum;
117 }
118 inline int query(int rt,int l,int r){
119     if(l<=T[rt].l&&T[rt].r<=r){
120         return T[rt].sum;
121     }
122     int mid=(T[rt].l+T[rt].r)>>1;
123     int ans=0;
124     if(l<=mid) ans+=query(rt<<1,l,r);
125     if(mid+1<=r) ans+=query(rt<<1|1,l,r);
126     return ans;
127 }
128 inline int Yougth(int u,int v){
129     int tp1=top[u],tp2=top[v];
130     if(u==v) return query(1,id[u],id[v]);
131     int ans=0;
132     while(tp1!=tp2){
133         if(dep[tp1]<dep[tp2]){
134             swap(tp1,tp2);
135             swap(u,v);
136         }
137         ans+=query(1,id[tp1],id[u]);
138         u=fa[tp1]; tp1=top[u];
139     }
140     if(dep[u]>dep[v]) swap(u,v);
141     ans+=query(1,id[u],id[v]);
142     return ans;
143 }
144 int main(){
145     scanf("%d",&N);
146     for(int i=1;i<=N;i++){
147         scanf("%d",&fa[i]);
148         son[fa[i]].push_back(i);
149     }
150     scanf("%d",&Q);
151     for(int i=1;i<=Q;i++){
152         scanf("%d",&q[i].kin);
153         if(q[i].kin==1){
154             scanf("%d%d%d",&q[i].from,&q[i].to,&q[i].c);
155             q[i].tim=i-q[i].c-1;
156             q[i].id=i;
157         }
158         else{
159             scanf("%d",&q[i].num);
160             q[i].tim=i;
161             q[i].id=i;
162         }
163     }
164     sort(q+1,q+Q+1,cmp1);
165     for(int i=1;i<=N;i++){
166         if(fa[i]==0){
167             dep[i]=0; p[i][0]=-1; dfs(i);   
168             dfs1(i,-1,1); dfs2(i,i);
169             break;
170         }
171     }
172     build(1,1,N);
173     for(int i=1;i<=Q;i++){
174         if(q[i].kin==2){
175             change(1,id[q[i].num],1);
176         }
177         else{
178             q[i].ans1=LCA(q[i].from,q[i].to)+1;
179             q[i].ans2=Yougth(q[i].from,q[i].to);
180         }
181     }
182     sort(q+1,q+Q+1,cmp2);
183     for(int i=1;i<=Q;i++){
184         if(q[i].kin==1){
185             printf("%d %d\n",q[i].ans1,q[i].ans2);
186         }
187     }
188     return 0;
189 }

 

以上是关于bzoj 4448: [Scoi2015]情报传递的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4448[Scoi2015]情报传递 主席树+LCA

BZOJ_4448_[Scoi2015]情报传递_主席树

bzoj4448: [Scoi2015]情报传递

4448: [Scoi2015]情报传递|主席树|离线操作

BZOJ 4448 情报传递

BZOJ [Scoi2015]情报传递