1. 程式人生 > >BZOJ5218[Lydsy2017省隊十連測] 友好城市

BZOJ5218[Lydsy2017省隊十連測] 友好城市

友好城市

Description

在Byteland 一共有n 座城市,編號依次為1 到n,這些城市之間通過m 條單向公路連線。對於兩座不同的城市a 和b,如果a 能通過這些單向道路直接或間接到達b,且b 也能如此到達a,那麼它們就會被認為是一對友好城市。Byteland 的交通系統十分特殊,第i 天只有編號在[li, ri] 的單向公路允許通行,請寫一個程式,計算每天友好城市的對數。 注意:(a, b) 與(b, a) 沒有區別。

Input

第一行包含三個正整數n, m, q,分別表示城市的個數、單向公路的條數以及詢問的天數。 接下來m 行,每行兩個正整數ui, vi,表示一條從城市ui 出發,通往城市vi 的單向道路。 接下來q 行,每行兩個正整數li, ri,表示一個詢問。 1 ≤ ui, vi ≤ n, ui != vi, 1 ≤ li ≤ ri ≤ m。N<=150,M<=300000,Q<=50000

Output

輸出q 行,每行一個整數,即友好城市的對數。

Sample Input

3 3 3 1 2 2 3 2 1 1 1 1 2 1 3

Sample Output

0 0 1

題解

HDU6072 Logical Chain實際上是一樣的,加個莫隊就能A,雖然正解是用分塊+ST表維護邊表。

程式碼

大家都加的莫隊憑什麼我被卡常???明明BZOJ過得賊快。

#include<bits/stdc++.h>
#define uint unsigned int
#define lg(x) __builtin_ctz(x)
using namespace std;
const int M=
160,bit=31,N=3e5+5; const uint inf=0xffffffff; struct sd{int a,b,id;}ed[N],ask[N]; uint mmp[M][M/bit],mmp2[M][M/bit],vis[M/bit]; int cot[M],sta[M],ans[N],cnt[M][M],top,T,n,m,q,tot,siz; bool operator<(sd x,sd y){return x.a/siz==y.a/siz?((x.a/siz&1)?x.b<y.b:x.b>y.b):x.a/siz<y.a/siz;} void dfs1(int
v){vis[v>>5]&=inf^(1<<(v&bit));for(int i=0;i<=(n>>5);++i)for(;mmp2[v][i]&vis[i];)dfs1(lg(mmp2[v][i]&vis[i])+(i<<5));sta[++top]=v;} void dfs2(int v){vis[v>>5]&=inf^(1<<(v&bit)),++cot[tot];for(int i=0;i<=(n>>5);++i)for(;mmp[v][i]&vis[i];dfs2(lg(mmp[v][i]&vis[i])+(i<<5)));} int work() { int i,ans;memset(cot,tot=top=ans=0,sizeof(cot)); for(memset(vis,255,sizeof(vis)),i=1;i<=n;++i)if(vis[i>>5]>>(i&bit)&1)dfs1(i); for(memset(vis,255,sizeof(vis)),i=top;i>=1;--i)if(vis[sta[i]>>5]>>(sta[i]&bit)&1)++tot,dfs2(sta[i]); for(int i=1;i<=tot;++i)ans+=cot[i]*(cot[i]-1)/2; return ans; } void add(int x){int a=ed[x].a,b=ed[x].b;if(!cnt[a][b]++)mmp[a][b>>5]|=1<<(b&bit),mmp2[b][a>>5]|=1<<(a&bit);} void del(int x){int a=ed[x].a,b=ed[x].b;if(!--cnt[a][b])mmp[a][b>>5]&=inf^(1<<(b&bit)),mmp2[b][a>>5]&=inf^(1<<(a&bit));} void in() { scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=m;++i)scanf("%d%d",&ed[i].a,&ed[i].b); for(int i=1;i<=q;++i)scanf("%d%d",&ask[i].a,&ask[i].b),ask[i].id=i; } void ac() { siz=sqrt(m);sort(ask+1,ask+1+q); int le=1,ri=1,i; for(add(1),i=1;i<=q;++i) { for(;le<ask[i].a;del(le++)); for(;le>ask[i].a;add(--le)); for(;ri<ask[i].b;add(++ri)); for(;ri>ask[i].b;del(ri--)); ans[ask[i].id]=work(); } for(int i=1;i<=q;++i)printf("%d\n",ans[i]); } int main(){in(),ac();}