190822 CSP-S 2019 模擬

A

艹居然被卡常了,100->50
這貌似是原題的加強版
加個hash亂搞一下就能過了
代碼:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	bool f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return f?ans:-ans;
}
typedef pair<int,int> pii;
const int mogic=1e6+7,N=1e5+5,M=5e5+5;
int n,m,Ask;
struct Hash_table1{
	vector<pii>ori[mogic];
	vector<int>idx[mogic];
	int tot;
	Hash_table1(){tot=0;}
	inline void update(const pii&a){
		int t=((ll)a.fi%mogic*n%mogic+a.se)%mogic;
		for(ri i=ori[t].size()-1;~i;--i)if(ori[t][i]==a)return;
		ori[t].push_back(a),idx[t].push_back(++tot);
	}
	inline int query(const pii&a){
		int t=((ll)a.fi%mogic*n%mogic+a.se)%mogic;
		for(ri i=ori[t].size()-1;~i;--i)if(ori[t][i]==a)return idx[t][i];
	}
}S1;
struct Hash_table2{
	vector<int>ori[mogic],idx[mogic];
	int tot;
	Hash_table2(){tot=0;}
	inline void update(const int&a){
		int t=a%mogic;
		for(ri i=ori[t].size()-1;~i;--i)if(ori[t][i]==a)return;
		ori[t].push_back(a),idx[t].push_back(++tot);
	}
	inline int query(const int&a){
		int t=a%mogic;
		for(ri i=ori[t].size()-1;~i;--i)if(ori[t][i]==a)return idx[t][i];
	}
}S2;
struct edge{int u,v,w;}e[M];
int pre1[M],all,col,sum=0,sig=0,qry[M];
vector<int>vis,ft2,vl2,rev2,siz2;
vector<edge>upd3[M<<2];
edge upd1[M];
struct stk4{
	vector<pii>Ft,Siz,Rev;
	inline void imodify(){
		pii x=Ft.back();
		Ft.pop_back();
		ft2[x.fi]=x.se;
		x=Siz.back();
		Siz.pop_back();
		siz2[x.fi]=x.se;
		x=Rev.back();
		Rev.pop_back();
		rev2[x.fi]=x.se;
	}
}q4;
struct Stk5{
	vector<int>Vl;
	inline void imodify(){
		int x=Vl.back();
		Vl.pop_back();
		vl2[x]=0;
		--sum;
	}
}q5;
struct Stk3{
	vector<int>Vis;
	inline void imodify(){
		int x=Vis.back();
		Vis.pop_back();
		vis[x]=0;
		--sig;
	}
}q3;
inline pii find2(int x){
	if(x==ft2[x])return pii(x,rev2[x]);
	pii t=find2(ft2[x]);
	return pii(t.fi,t.se^rev2[x]);
}
inline void addedge2(edge a){
	int x=S1.query(pii(a.w,a.u)),y=S1.query(pii(a.w,a.v)),coll=S2.query(a.w);
	if(vl2[coll])return;
	pii fx=find2(x),fy=find2(y);
	if(!vis[coll]){
		q3.Vis.push_back(coll);
		vis[coll]=1;
		++sig;
	}
	if(fx.fi^fy.fi){
		if(siz2[fx.fi]<siz2[fy.fi])swap(fx,fy);
		q4.Ft.push_back(pii(fy.fi,ft2[fy.fi])),ft2[fy.fi]=fx.fi;
		q4.Siz.push_back(pii(fx.fi,siz2[fx.fi])),siz2[fx.fi]+=siz2[fy.fi];
		q4.Rev.push_back(pii(fy.fi,rev2[fy.fi]));
		if(fx.se==fy.se)rev2[fy.fi]^=1;
		return;
	}
	else if(fx.se==fy.se){
		q5.Vl.push_back(coll);
		vl2[coll]=1;
		++sum;
	}
}
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (l+r>>1)
int cnt=0;
inline void update3(int p,int l,int r,int ql,int qr,edge v){
	if(ql>qr)return;
	if(ql<=l&&r<=qr){upd3[p].push_back(v);return;}
	if(qr<=mid)update3(lc,l,mid,ql,qr,v);
	else if(ql>mid)update3(rc,mid+1,r,ql,qr,v);
	else update3(lc,l,mid,ql,qr,v),update3(rc,mid+1,r,ql,qr,v); 
}
inline void solve(int p,int l,int r){
	int cur3=q3.Vis.size(),cur4=q4.Ft.size(),cur5=q5.Vl.size();
	for(ri i=0,up=upd3[p].size();i<up;++i)addedge2(upd3[p][i]);
	if(l==r){
		if(~qry[l]){
			cout<<(vl2[S2.query(qry[l])]?"NO\n":"YES\n");
			if(upd1[l].u)addedge2(upd1[l]);
			cout<<sig-sum<<'\n';
		}
		while(q3.Vis.size()!=cur3)q3.imodify();
		while(q4.Ft.size()!=cur4)q4.imodify();
		while(q5.Vl.size()!=cur5)q5.imodify();
		return;
	}
	solve(lc,l,mid),solve(rc,mid+1,r);
	while(q3.Vis.size()!=cur3)q3.imodify();
	while(q4.Ft.size()!=cur4)q4.imodify();
	while(q5.Vl.size()!=cur5)q5.imodify();
}
#undef lc
#undef rc
#undef mid
struct Qry{
	int op,a,b;
}Q[M];
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	freopen("std.out","w",stdout);
	#endif
	n=read(),m=read(),Ask=read();
	for(ri w,u,v,i=1;i<=m;++i){
		w=read(),u=read(),v=read();
		S1.update(pii(w,u)),S1.update(pii(w,v));
		S2.update(w);
		e[i]=(edge){u,v,w};
		pre1[i]=1;
	}
	int tot=0;
	for(ri i=1;i<=Ask;++i){
		Q[i].op=read();
		Q[i].a=read();
		if(!Q[i].op)Q[i].b=read(),++tot;
	}
	for(ri i=1,a,b,cnt=0;i<=Ask;++i){
		a=Q[i].a,b=Q[i].b;
		if(!Q[i].op){
			++cnt;
			qry[cnt]=a;
			if(b){
				update3(1,1,tot,pre1[b],cnt-1,e[b]);
				upd1[cnt]=e[b];
				pre1[b]=cnt+1;
			}
			S2.update(a);
		}
		else{
			b=Q[i].a,a=Q[i].op;
			update3(1,1,tot,pre1[a],cnt,e[a]);
			pre1[a]=cnt+1,e[a].w=b;
			S1.update(pii(e[a].w,e[a].u));
			S1.update(pii(e[a].w,e[a].v));
			S2.update(e[a].w);
		}
	}
	for(ri i=1;i<=m;++i)update3(1,1,tot,pre1[i],tot,e[i]);
	all=S1.tot,col=S2.tot;
	vis.resize(col+1);
	ft2.resize(all+1),siz2.resize(all+1),rev2.resize(all+1);
	vl2.resize(col+1);
	for(ri i=1;i<=all;++i)ft2[i]=i,siz2[i]=1,rev2[i]=0;
	solve(1,1,tot);
	return 0;
}

B

暫時咕掉
留坑

C

如果是棵樹就是點分治+ntt板題,現在變成了基環樹,由於保證環上的點很少因此可以暴力枚舉子樹的貢獻。
代碼:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mod=1004535809;
typedef long long ll;
typedef vector<int> poly;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;} 
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
int w[21],invv[21];
vector<int>rev[21];
inline void init_w(){
	w[20]=ksm(3,(mod-1)>>21),invv[0]=1;
	for(ri i=19;~i;--i)w[i]=mul(w[i+1],w[i+1]);
	for(ri i=1,iv=mod+1>>1;i<21;++i)invv[i]=mul(invv[i-1],iv);
}
int lim,tim;
inline void init(const int&up){
	lim=1,tim=0;
	while(lim<up)lim<<=1,++tim;
	if(rev[tim].size())return;
	rev[tim].resize(lim);
	for(ri i=1;i<lim;++i)rev[tim][i]=(rev[tim][i>>1]>>1)|((i&1)<<(tim-1));
}
inline void ntt(poly&a,const int&type){
	for(ri i=0;i<lim;++i)if(i<rev[tim][i])swap(a[i],a[rev[tim][i]]);
	for(ri i=1,t=0,a0,a1;i<lim;i<<=1,++t)for(ri j=0,len=i<<1;j<lim;j+=len)
	for(ri k=0,mt=1;k<i;++k,Mul(mt,w[t]))a0=a[j+k],a1=mul(mt,a[j+k+i]),a[j+k]=add(a0,a1),a[j+k+i]=dec(a0,a1);
	if(~type)return;
	reverse(++a.begin(),a.end());
	for(ri i=0;i<lim;++i)Mul(a[i],invv[tim]); 
}
inline poly operator*(poly a,poly b){
	int n=a.size(),m=b.size(),t=n+m-1;
	if(t<=128){
		poly c(t);
		for(ri i=0;i<n;++i)for(ri j=0;j<m;++j)Add(c[i+j],mul(a[i],b[j]));
		return c;
	}
	init(t);
	a.resize(lim),ntt(a,1);
	b.resize(lim),ntt(b,1);
	for(ri i=0;i<lim;++i)Mul(a[i],b[i]);
	return ntt(a,-1),a.resize(t),a;
}
const int N=1e5+5;
int n,top=0,stk[N],cnt[N],siz[N];
vector<int>e[N],lp;
bool in[N];
vector<poly>lopdis;
void findloop(int p,int fa){
	in[p]=1,stk[++top]=p;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa)continue;
		if(in[v]){
			if(lp.size())continue;
			int t=top;
			while(1){
				lp.push_back(stk[t]);
				if(stk[t]==v)break;
				--t;
			}
			continue;
		}
		findloop(v,p);
	}
	in[p]=0,--top;
}
double ans=0;
int cnt1[N],cnt2[N],mxdep,alldep,all,rt,msz;
void getsize(int p,int fa){
	siz[p]=1;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa||in[v])continue;
		getsize(v,p),siz[p]+=siz[v];
	}
}
void getroot(int p,int fa){
	siz[p]=1;
	int ms=0;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa||in[v])continue;
		getroot(v,p),siz[p]+=siz[v];
		ms=max(ms,siz[v]);
	}
	if((ms=max(ms,all-siz[p]))<msz)msz=ms,rt=p;
}
void getdist(int p,int fa,int dist){
	++cnt2[dist],mxdep=max(mxdep,dist);
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa||in[v])continue;
		getdist(v,p,dist+1);
	}
}
inline void update_ans(poly a,int ad,int coe){for(ri i=a.size()-1;i;--i)if(a[i])ans+=1.0*coe*a[i]/(i+ad);}
inline void update(){
	poly a,b;
	a.resize(alldep+1),b.resize(mxdep+1);
	for(ri i=1;i<=alldep;++i)a[i]=cnt1[i];
	alldep=max(alldep,mxdep+1);
	for(ri i=1;i<=mxdep;++i)cnt1[i+1]+=(b[i]=cnt2[i]),cnt2[i]=0;
	update_ans(a*b,0,1);
}
void solve(int p,bool f){
	in[p]=1;
	for(ri i=1;i<=alldep;++i)cnt1[i]=0;
	alldep=1,cnt1[1]=1;
	for(ri i=0,v;i<e[p].size();++i){
		if(in[v=e[p][i]])continue;
		mxdep=0;
		getdist(v,p,1);
		update();
	}
	getsize(p,0);
	for(ri i=0,v;i<e[p].size();++i){
		if(in[v=e[p][i]])continue;
		all=msz=siz[v],rt=0;
		getroot(v,p),solve(rt,0);
	}
}
int main(){
	init_w();
	n=read();
	for(ri i=1,u,v;i<=n;++i){
		u=read(),v=read();
		e[u].push_back(v),e[v].push_back(u);
	}
	findloop(1,0);
	for(ri i=lp.size()-1;~i;--i)in[lp[i]]=1;
	lopdis.resize(lp.size());
	for(ri i=lp.size()-1;~i;--i){
		in[lp[i]]=0;
		mxdep=0;
		getdist(lp[i],0,1);
		lopdis[i].resize(mxdep+1);
		for(ri j=1;j<=mxdep;++j)lopdis[i][j]=cnt2[j],cnt2[j]=0;
		getsize(lp[i],0);
		rt=0,all=msz=siz[lp[i]];
		getroot(lp[i],0),solve(rt,1);
		in[lp[i]]=1;
	}
	double t=ans;
	for(ri a,b,i=lp.size()-1;~i;--i)for(ri j=i-1;~j;--j){
		a=i-j-1,b=lp.size()-i+j-1;
		poly t=lopdis[i]*lopdis[j];
		update_ans(t,a,1);
		update_ans(t,b,1);
		update_ans(t,a+b,-1);
	}
	printf("%.6lf",ans*2.0/n+1);
	return 0;
}

考試總結:
BBKMPKMP部分分寫錯也挺讓人無語的吧(雖然檢查過
AA被卡常搞得我徹底自閉了(本地挺快的不知道WSM被老爺機卡了
CC那個套路完全不會,現在getget到一種新技能QvQ

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章