$IcePrincess\text{_}1968$和$IcePrince\text{_}1968$長大了,他們開始協助國王$IceKing\text{_}1968$管理國內事物。
$IcePrincess\text{_}1968$和$IcePrince\text{_}1968$住在一個寧靜悠遠的王國:$IceKingdom$——飄雪聖域。飄雪聖域有$n$個城鎮,編號$1,2,3...n$。有些城鎮之間有道路,且知足任意兩點之間有且僅有一條路徑。飄雪聖域風景優美,但氣候並非太好。根據$IcePrince\text{_}1968$的氣候探測儀,未來會發生$q$場暴風雪。每場暴風雪能夠用兩個整數$l_i,r_i$刻畫,表示這場暴風雪以後,只有編號屬於$[l_i,r_i]$的城市沒有受到暴風雪的影響。
在暴風雪的影響下迅速肯定王國的農業生產方案是很是重要的事情。$IceKing\text{_}1968$認爲,一個農業生產地域應該是一個極大連通塊,知足每一個節點都沒有被暴風雪影響。這裏極大連通塊的定義是:不存在一個不屬於該點集的未被暴風雪影響的點與該連通塊連通。
$IcePrincess\text{_}1968$要負責算出每次暴風雪後,王國能擁有多少個農業生產地域。注意這裏每次暴風雪是獨立的,即每次暴風雪事後,直到每一個城鎮從新煥發生機,下一次暴風雪纔會到來。
正如上文所述,$IcePrincess\text{_}1968$擅長文學但不擅長計算機,因而請你幫忙。node
輸入文件名爲$icekingdom.in$。
第一行包含兩個正整數$n,q$,表示$IceKingdom$的城鎮個數和暴風雪次數。
第$2$至第$n$行,每行兩個正整數$x,y$,表示城鎮$x$和城鎮$y$之間有一條道路。
第$n+1$至第$n+q$行,每行兩個正整數$l_i,r_i$,描述一場暴風雪,含義如題面所述。c++
輸出文件名$icekingdom.out$。
輸出文件共有$q$行,第$i$行表示在第$i$場暴風雪以後農業生產地域的個數。數據結構
樣例輸入:dom
4 3
1 2
2 3
2 4
1 2
1 3
3 4spa
樣例輸出:blog
1
1
2it
樣例解釋:io
第一次詢問,只有$(1,2)$一個連通塊。
第二次詢問,只有$(1,2,3)$一個連通塊。
第三次詢問,有$3$和$4$兩個連通塊。class
數據範圍:方法
對於$30\%$的數據:$n\leqslant 100,q\leqslant 100$;
對於$50\%$的數據:$n\leqslant 2,000,q\leqslant 2,000$;
對於$100\%$的數據:$n\leqslant 200,000,q\leqslant 200,000$,對於全部的暴風雪,$l_i\leqslant r_i$。
官方正解中的兩種作法都是用的數據結構,然而我用的是莫隊……
加一個點它對答案的貢獻是$1-$與它鏈接的沒有受到暴風雪影響的點,$1$是由於它本身能夠做爲一個新的聯通塊,減去沒有收到暴風雪影響的點是由於它會合並這些聯通塊;刪點同理。
顯然$200,000$的數據範圍莫隊必定要有$\Theta(1)$修改的方法。
不妨以加的操做爲例,爲作到$\Theta(1)$修改,就須要找到方法快速求出與它鏈接的沒有受到暴風雪影響的點。
先預處理出來全部點的父親,並設$num[x]$爲點$x$的兒子中沒有受到暴風雪影響的點的個數,加入一個點的同時將它父親的$num+1$便可,注意統計答案時不要忘了父親。
刪點同理。
時間複雜度:$\Theta(n\sqrt{n})$。
指望得分:$100$分。
實際得分:$100$分。
#include<bits/stdc++.h>
using namespace std;
struct node{int nxt,to;}e[500000];
struct rec{int l,r,pos,id;}q[200001];
int head[200001],cnt;
int n,m;
int ans[200001],l,r,now;
int num[200001],fa[200001];
bool vis[200001];
void add(int x,int y)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
bool cmp(rec a,rec b){return (a.pos)^(b.pos)?a.l<b.l:(((a.pos)&1)?a.r<b.r:a.r>b.r);}
void add(int x)
{
vis[x]=1;
now++;
now-=num[x];
num[fa[x]]++;
if(vis[fa[x]])now--;
}
void del(int x)
{
vis[x]=0;
now--;
now+=num[x];
num[fa[x]]--;
if(vis[fa[x]])now++;
}
void dfs(int x)
{
for(int i=head[x];i;i=e[i].nxt)
if(!fa[e[i].to]&&e[i].to>1){fa[e[i].to]=x;dfs(e[i].to);}
}
int main()
{
scanf("%d%d",&n,&m);
int t=sqrt(n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs(1);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].pos=(q[i].l-1)/t+1;
q[i].id=i;
}
sort(q+1,q+m+1,cmp);
l=r=1;add(1);
for(int i=1;i<=m;i++)
{
while(l>q[i].l)add(--l);
while(r<q[i].r)add(++r);
while(l<q[i].l)del(l++);
while(r>q[i].r)del(r--);
ans[q[i].id]=now;
}
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}
rp++