列表

详情


NC227022. 骄傲无知的现代人不知道珍惜(T5)

描述

现代化的都市总是错综复杂,一不小心就让人找不回自己。

形式化的说,都市共有 n 个重要地点。最开始,你可以认为都市中没有道路。每个地点有一个重要程度,设为 a。第 i 个地点的重要程度为 a_i

时代变迁,沧海桑田。一瞬间,q 年过去,都市迎来了百年未有之大变局。在时代的风口,我们回望过去,体会荣辱;在时代的浪尖,我们远瞻未来,扬帆起航。

根据以上材料,写一篇文章。(划掉)

在 q 年内,每一年会恰好发生一件♂事。具体地,如下:
  • 0 x y,新建了一条道路,从 x 到 y。
  • 1 k,删去了第 k 条新建的道路。保证第 k 条边之前未被删除。
每次操作后,都要询问现代化都市的都市生产指数(Grass City Product Indicator,GCPI)。具体地,其定义为所有联通块的 GCPI 对 mod 取模后的最大值,其中 mod 为一个膜♂法参数。

一个连通块的 GCPI 定义为组合数 ,其中 V 表示连通块的所有地点的重要度总和,N 表示连通块地点的数目。

输入描述

第一行三个数,n,q 和 mod。  

第二行 n 个数表示重要度。

后接 q 行,每行一个操作。

输出描述

q 行,每行一个数,表示答案。

示例1

输入:

4 6 1145141
1 1 4 5
0 1 2
0 2 3
0 3 1
0 4 3
1 2
1 1

输出:

5
20
20
330
330
120

说明:

n\le 80000, q\le 80000,重要度非负,a_i \le 2e9。请注意实现常数。
mod 只可能是以下数中的一个:
4580564 1145141 100160063 102101809 

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 2878ms, 内存消耗: 29848K, 提交时间: 2021-09-11 12:17:33

#include <bits/stdc++.h>
using namespace std;
#define M 80005
typedef long long  LL;
template<class T>bool tomax(T &x,T y){
	if(x<y)return x=y,1;
	return 0;
}
template<class T>bool tomin(T &x,T y){
	if(x>y)return x=y,1;
	return 0;
}
template<class T>void Rd(T &x){
	static char c;
	while(c=getchar(),!isdigit(c));
	for(x=0;isdigit(c);c=getchar())
		x=(x<<1)+(x<<3)+(c^48);
}
template<class T>void Ps(T x){
	if(x==0)return;
	Ps(x/10);putchar(x%10^48);
}
template<class T>void Printf(T x){
	if(x==0)putchar(48);
	else Ps(x);
	puts("");
}
bool MM1;
vector<int>num;
void exgcd(LL a,LL b,LL &x,LL &y){
	if(!b){x=1,y=0;return;}
	exgcd(b,a%b,y,x),y-=a/b*x; 
}
LL Inv(LL a,LL b){
	LL x,y;
	exgcd(a,b,x,y);
	return (x%b+b)%b;
}
LL exCRT(LL a1,LL b1,LL a2,LL b2){
	LL MOD=a1*a2;
	return ( (b2-b1+MOD)*a1%MOD*Inv(a1,a2)+b1 )%MOD;
}
int n,q,P;
void Mul(int &x,int y){
	x=1LL*x*y%P;
}
int qikpow(int a,LL b){
	int ret=1;
	for(;b;b>>=1,Mul(a,a))
		if(b&1)Mul(ret,a);
	return ret;
}
#define calc(x,y) x=((y)+x)%P
int fec[5][1145141];
void Init(int t){
	fec[t][0]=fec[t][1]=1;
	P=num[t];
	int tmp=sqrt(P);
	if(tmp*tmp!=P)tmp=P;
	for(int i=2;i<P;i++){
		if(i%tmp!=0)fec[t][i]=1LL*fec[t][i-1]*i%P;
		else fec[t][i]=fec[t][i-1]; 
	}
}
int Ans[M];
multiset<int>ans;
vector<pair<int,int> >E[M<<2];
pair<LL,int> Fec(LL x,int p,int t){
	if(!x)return make_pair(0,1);
	pair<LL,int> ret=Fec(x/p,p,t);
	ret.first+=x/p;
	Mul(ret.second, qikpow(fec[t][P-1],x/P) );
	Mul(ret.second, fec[t][x%P] );
	return ret;
}
int C(LL a,LL b,int p,int t){
	pair<LL,int>x=Fec(a,p,t),y=Fec(b,p,t),z=Fec(b-a,p,t);
	if(y.first-x.first-z.first>=2)return 0;
	int ret=1LL*y.second*Inv(x.second,P)%P*Inv(z.second,P)%P;
	if(y.first-x.first-z.first==1)return 1LL*ret*p%P;
	return ret;
}
int exLucas(LL a,LL b){
	if(a>b)return 0;
	int p=1,ret=0;
	for(int i=0;i<num.size();i++){
		P=num[i];
		int q=sqrt(P);
		if(q*q!=P)q=P;
		int B=C(a,b,q,i);
		if(i==0)ret=B;
		else ret=exCRT(p,ret,P,B);
		p*=num[i];
	}
	return ret;
}
int Val[M];
struct UNION{
	int f[M],dep[M],sz[M];
	LL A[M];
	void Init(){
		for(int i=1;i<=n;i++)f[i]=i,dep[i]=1,sz[i]=1,A[i]=Val[i];
	}
	int find(int p){
		while(p!=f[p])p=f[p];
		return p;
	}
	struct NODE{
		int a,b,d;
		int x,y,z;
	};
	NODE stk[M];
	int top; 
	bool Merge(int a,int b){
		a=find(a),b=find(b);
		if(a==b)return 0;
		if(dep[a]>dep[b])swap(a,b);
		int x=exLucas(sz[b],A[b]),y=exLucas(sz[a],A[a]),z=exLucas(sz[a]+sz[b],A[a]+A[b]);
		ans.erase(ans.lower_bound(-x));
		ans.erase(ans.lower_bound(-y));
		ans.insert(-z);
		A[b]+=A[a],sz[b]+=sz[a];
		stk[++top]=(NODE){a,b,dep[b],x,y,z};
		tomax(dep[b],dep[a]+1);
		f[a]=b;
		return 1;
	}
	void Back(){
		NODE x=stk[top--];
		f[x.a]=x.a;
		sz[x.b]-=sz[x.a];
		A[x.b]-=A[x.a];
		dep[x.b]=x.d;
		ans.insert(-x.x);
		ans.insert(-x.y);
		ans.erase(ans.lower_bound(-x.z));
	}
}F;
void Push(int l,int r,int L,int R,pair<int,int> x,int p){
	if(l==L&&R==r)return void(E[p].push_back(x));
	int mid=l+r>>1;
	if(R<=mid)Push(l,mid,L,R,x,p<<1);
	else if(L>mid)Push(mid+1,r,L,R,x,p<<1|1);
	else Push(l,mid,L,mid,x,p<<1),Push(mid+1,r,mid+1,R,x,p<<1|1);
}
void Solve(int l,int r,int p){
	int sz=0;
	for(int i=0;i<E[p].size();i++)
		sz+=F.Merge(E[p][i].first,E[p][i].second);
	if(l==r)Ans[l]=-(*ans.begin());
	else{
		int mid=l+r>>1;
		Solve(l,mid,p<<1);
		Solve(mid+1,r,p<<1|1);
	}	
	while(sz--)F.Back();
}
int m,ID[M],mark[M],pri[M],tt;
pair<int,int>edge[M];
bool MM2;
int main(){
//	printf("%lf\n",(&MM2-&MM1)/1024.0/1024.0);
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int p;
	Rd(n),Rd(q),Rd(p);
	for(int i=1;i<=n;i++)Rd(Val[i]);
	for(int i=1;i<=n;i++)ans.insert(-(Val[i]%p));
	for(int i=1;i<=q;i++){
		int op,x,y;
		Rd(op);
		if(op==0){
			Rd(x),Rd(y);
			edge[++m]=make_pair(x,y);
			ID[m]=i;
		}else{
			Rd(x);
			Push(1,q,ID[x],i-1,edge[x],1);
			ID[x]=0;
		}
	}
	for(int i=1;i<=m;i++)if(ID[i]!=0)Push(1,q,ID[i],q,edge[i],1);
	int ed=sqrt(p);
	for(int i=2;i<=ed;i++){
		if(!mark[i])pri[++tt]=i;
		else continue;
		for(int j=i+i;j<=ed;j+=i)mark[j]=1;
	}
	for(int i=1;i<=tt;i++){
		int t=1;
		while(p%pri[i]==0)t*=pri[i],p/=pri[i];
		if(t>1)num.push_back(t);
	} 
	if(p>1)num.push_back(p);
	for(int i=0;i<num.size();i++)Init(i);
	F.Init();
	Solve(1,q,1);
	for(int i=1;i<=q;i++)Printf(Ans[i]);
	return 0;
} 

上一题