BZOJ5218[Lydsy2017省隊十連測] 友好城市
阿新 • • 發佈:2018-12-12
友好城市
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();}