BZOJ [Scoi2015]情報傳遞
阿新 • • 發佈:2017-10-03
tree algo bzoj ring query 其余 %d urn num
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
5 2
5 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
題解:
這個題目,樹鏈剖分是十分顯然的,但是怎麽進行修改呢?
首先我們可以知道,我們把詢問按照i-c來排序,i-c-1就是對答案可以做出貢獻的最大修改操作的標號,然後我們把修改詢問按標號來排序,那麽對於一個詢問i,我們考慮加入修改操作,如果當前的修改操作的標號x<i-c,那麽顯然他可以對答案做出貢獻,我們就執行修改,直到x>i-c,為止,再進行查詢操作,因為我們的修改操作的指針是單調的,不需要將加過的點改回去,所以復雜度是對的。
但為什麽能保證是正確的呢?顯然C是大於0的,所以第i個決策所要求的修改操作的標號一定是在他之前的,就不可能將其後面的操作加入,所以正確。
這個離線還是比較巧妙!
代碼:
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
70 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 05 2
5 1
HINT
對於3個傳遞情報任務,都是經過5名情報員,分別是4號、2號、1號、3號和7號。其中,對於第1個
任務,所有情報員(危險值為0)都不對情報構成威脅;對於第2個任務,有2名情報員對情報構成威脅,
分別是1號情報員(危險值為3)和4號情報員(危險值為2),7號情報員(危險值為1)並不構成威脅;
對於第3個任務,只有1名情報員對情報構成威脅。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define MAXN 201000 using namespace std; struct tree{ int sum1,sum2,l,r; }tr[MAXN*5]; struct que{ int id,x,y,c,t,ans1,ans2; }q1[MAXN]; struct que2{ int id,x,d; }q2[MAXN]; struct edge{ int first,next,to; }a[MAXN*2]; int dep[MAXN],fa[MAXN],size[MAXN],son[MAXN],top[MAXN],pos[MAXN]; int n,q,num=0,num2=0,cnt=0,cnt2=0; void addedge(int from,int to){ a[++num].to=to; a[num].next=a[from].first; a[from].first=num; } void dfs1(int now,int f){ fa[now]=f,size[now]=1,dep[now]=dep[f]+1; for(int i=a[now].first;i;i=a[i].next){ int to=a[i].to; if(to==f) continue; dfs1(to,now); size[now]+=size[to]; if(size[son[now]]<size[to]) son[now]=to; } } void dfs2(int now,int tp){ top[now]=tp,pos[now]=++num2; if(son[now]) dfs2(son[now],tp); for(int i=a[now].first;i;i=a[i].next){ int to=a[i].to; if(to==fa[now]||to==son[now]) continue; dfs2(to,to); } } bool cmp(que x,que y){if(x.t!=y.t)return x.t<y.t;else return x.id<y.id;} bool cmp2(que2 x,que2 y){return x.id<y.id;} bool cmp3(que x,que y){return x.id<y.id;} int query(int xv,int L,int R,int l,int r,int hh){ if(l==L&&r==R){ if(hh==1) return tr[xv].sum1; else return tr[xv].sum2; } int mid=(L+R)/2; if(r<=mid) return query(xv*2,L,mid,l,r,hh); else if(l>mid) return query(xv*2+1,mid+1,R,l,r,hh); else return query(xv*2,L,mid,l,mid,hh)+query(xv*2+1,mid+1,R,mid+1,r,hh); } void getans(int hh){ int x=q1[hh].x,y=q1[hh].y,topx=top[x],topy=top[y],ans1=0,ans2=0; while(topx!=topy){ if(dep[topx]<dep[topy]) swap(topx,topy),swap(x,y); ans1+=query(1,1,num2,pos[topx],pos[x],1); ans2+=query(1,1,num2,pos[topx],pos[x],0); x=fa[topx]; topx=top[x]; } if(dep[x]<dep[y]) swap(x,y); ans1+=query(1,1,num2,pos[y],pos[x],1); ans2+=query(1,1,num2,pos[y],pos[x],0); q1[hh].ans1=ans1,q1[hh].ans2=ans2; } void change(int xv,int L,int R,int id,int hh){ if(L==R&&L==id){ if(hh==1) tr[xv].sum1=1; else tr[xv].sum2=1; return; } int mid=(L+R)/2; if(id<=mid) change(xv*2,L,mid,id,hh); else change(xv*2+1,mid+1,R,id,hh); tr[xv].sum1=tr[xv*2].sum1+tr[xv*2+1].sum1; tr[xv].sum2=tr[xv*2].sum2+tr[xv*2+1].sum2; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ int x;scanf("%d",&x); addedge(i,x),addedge(x,i); } dfs1(1,0);dfs2(1,1); scanf("%d",&q); for(int i=1;i<=q;i++){ int id;scanf("%d",&id); if(id==1){ int x,y,c;scanf("%d%d%d",&x,&y,&c);cnt++; q1[cnt].x=x,q1[cnt].y=y,q1[cnt].c=c,q1[cnt].t=i-c,q1[cnt].id=i; } else{ int x;scanf("%d",&x); q2[++cnt2].x=x;q2[cnt2].id=i; } } sort(q1+1,q1+cnt+1,cmp); sort(q2+1,q2+cnt2+1,cmp2); int now=1; for(int i=1;i<=n;i++) change(1,1,num2,pos[i],2); for(int i=1;i<=cnt;i++){ while(now<=cnt2&&q2[now].id<q1[i].t){ change(1,1,num2,pos[q2[now].x],1);now++; } getans(i); } sort(q1+1,q1+cnt+1,cmp3); for(int i=1;i<=cnt;i++){ printf("%d %d\n",q1[i].ans2,q1[i].ans1); } return 0; }
BZOJ [Scoi2015]情報傳遞