[2018.10.23 T1] 戰爭

暫無鏈接

戰爭

【題目描述】

人類在火星上的殖民地日漸發達,它們之間自然地構建起了多條交通運輸道路,形成一個樹狀結構。

具體的說,人類在火星上已經有了nn個殖民地,用編號1n1\sim n表示,這nn個殖民地由n1n−1條邊連通。

同時,編號爲i殖民地擁有一定的文明點數wiw_i,並且wi=iw_i=i。兩個殖民地u,vu,v可以交流併產生文明價值,當且僅當u,vu,v連通,交流產生的文明價值爲wu×wvw_u×w_v,不連通的殖民地無法產生文明價值。火星的文明價值即爲所有殖民地點對u,vu,v的文明價值的和。

公元23332333年,外星文明進攻了火星。這一場浩劫導致一些殖民地在許多場先後進行的戰爭中被破壞,一共進行了mm場戰爭,每一場戰爭有多個殖民地被破壞。破壞後的殖民地殘存大量輻射寸草不生,既無法被經過也無法與其他殖民地交流。全球陷入了空前的危機。

爲了做好最壞的打算,你希望可以準確計算出戰爭爆發前(沒有殖民地被破壞時)火星的文明價值,以及每輪戰鬥後,火星現存的文明價值。

【輸入】

第一行兩個正整數: n,mn,m分別表示殖民地個數和戰爭場數

第二行n1n−1個整數,第ii個數fif_i代表殖民地i+1i+1fif_i有一條道路(0<fii)(0<f_i≤i)

接下來依次有mm行:

ii行第一個數爲正整數kk,接下來kk個數分別代表第ii時刻被破壞的殖民地編號。

【輸出】

一共有m+1m+1行輸出。

第一行輸出在00時刻的答案,

22m+1m+1行分別輸出一個整數sumsum表示第i1i−1時刻後(即一些殖民地在i−1時刻被破壞後)的答案。(注:答案對(109+710^9+7)取模)

【輸入樣例】

3 2
1 2
1 2
1 3

【輸出樣例】

11
0
0

【提示】
【數據範圍】

對於30%30\%的數據:n200n≤200
對於60%60\%的數據:n2000n≤2000
對於100%100\%的數據:n106,mnn≤10^6,m≤n

題解

離線刪除操作,倒着做插入操作,加入點後如果聯通塊個數減少,新聯通塊的權值即爲原來兩個聯通塊的權值之和加上兩權值之積。

所以我們大力並查集,維護聯通塊權值和即可。

代碼
#include<bits/stdc++.h>
#define pos add[i][j]
using namespace std;
const int M=1e6+6,mod=1e9+7;
int f[M],ans[M],val[M],n,m,r;
bool gg[M];
char c;
vector<int>add[M],mmp[M];
int read()
{
	for(r=0;!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())r=(r<<1)+(r<<3)+c-'0';
	return r;
}
void out(int x)
{
	if(x>9)out(x/10);
	putchar(x%10+'0');
}
int root(int v){return f[v]==v?v:f[v]=root(f[v]);}
void link(int x,int y){if(root(x)==root(y))return;(val[root(y)]+=val[root(x)])%=mod;f[root(x)]=root(y);}
void in()
{
	n=read(),m=read();
	for(int i=2,a;i<=n;++i)a=read(),mmp[a].push_back(i),mmp[i].push_back(a);
	for(int i=1,j,a,b;i<=m;++i)
	for(a=read(),j=1;j<=a;++j)b=read(),add[i].push_back(b),gg[b]=1;
}
void ac()
{
	for(int i=1;i<=n;++i)f[i]=val[i]=i;
	for(int i=1;i<=n;++i)
	if(!gg[i])for(int j=mmp[i].size()-1;j>=0;--j)
	if(!gg[mmp[i][j]]&&root(i)!=root(mmp[i][j]))
	ans[m+1]+=val[root(i)]*val[root(mmp[i][j])],link(i,mmp[i][j]);
	for(int i=m;i;--i)
	{
		ans[i]=ans[i+1];
		for(int j=add[i].size()-1;j>=0;--j)gg[add[i][j]]=0;
		for(int j=add[i].size()-1;j>=0;--j)
		for(int k=mmp[pos].size()-1;k>=0;--k)
		if(!gg[mmp[pos][k]]&&root(mmp[pos][k])!=root(pos))
		(ans[i]+=1ll*val[root(mmp[pos][k])]*val[root(pos)]%mod)%=mod,link(mmp[pos][k],pos);
	}
	for(int i=1;i<=m+1;++i)out(ans[i]),putchar(10);
}
int main(){in(),ac();}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章