ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

省选测试14

2021-02-02 07:34:33  阅读:140  来源: 互联网

标签:ch 14 省选 int rg maxn 测试 include mod


总结

前面三位 \(AK\) 大佬

这一套题的难度确实不高,仔细想一下每一道题应该都是能做出来的

但是 \(T1\) 一个 \(lct\) 的板子调了 \(3\) 个小时实在是说不过去

后面两道题没有时间思考,只能打暴力

所以板子打熟很重要

A. 选择

分析

\(lct\) 维护双联通分量

和长跑那道题挺像的

lct学习笔记

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<map>
#define rg register
inline int read(){
	rg int x=0,fh=1;
	rg char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=1e6+5;
struct DSU{
	int fa[maxn];
	void init(){
		for(rg int i=1;i<maxn;i++) fa[i]=i;
	}
	int zhao(rg int xx){
		if(fa[xx]==xx) return xx;
		return fa[xx]=zhao(fa[xx]);
	}
}dsu;
struct LCT{
	int rev[maxn],ch[maxn][2],fa[maxn],sta[maxn],tp;
	void push_down(rg int da){
		if(rev[da]==0) return;
		rg int lc=ch[da][0],rc=ch[da][1];
		rev[lc]^=1,rev[rc]^=1,rev[da]^=1;
		std::swap(ch[da][0],ch[da][1]);
	}
	bool isroot(rg int da){
		return ch[fa[da]][0]!=da&&ch[fa[da]][1]!=da;
	}
	void xuanzh(rg int x){
		rg int y=fa[x];
		rg int z=fa[y];
		rg int k=(ch[y][1]==x);
		if(!isroot(y)) ch[z][ch[z][1]==y]=x;
		fa[x]=z;
		ch[y][k]=ch[x][k^1];
		fa[ch[x][k^1]]=y;
		ch[x][k^1]=y;
		fa[y]=x;
	}
	void splay(rg int x){
		sta[tp=1]=x;
		for(rg int i=x;!isroot(i);i=fa[i]) sta[++tp]=fa[i];
		for(rg int i=tp;i>=1;i--) push_down(sta[i]);
		while(!isroot(x)){
			rg int y=fa[x];
			rg int z=fa[y];
			if(!isroot(y)){
				(ch[y][1]==x)^(ch[z][1]==y)?xuanzh(x):xuanzh(y);
			}
			xuanzh(x);
		}
	}
	void access(rg int x){
		for(rg int y=0;x;y=x,x=dsu.zhao(fa[x])){
			splay(x);
			ch[x][1]=y;
			fa[y]=x;
		}
	}
	void makeroot(rg int x){
		access(x);
		splay(x);
		rev[x]^=1;
		push_down(x);
	}
	int findroot(rg int x){
		access(x);
		splay(x);
		push_down(x);
		while(ch[x][0]){
			x=ch[x][0];
			push_down(x);
		}
		splay(x);
		return x;
	}
	void split(rg int x,rg int y){
		makeroot(x);
		access(y);
		splay(y);
	}
	void link(rg int x,rg int y){
		makeroot(x);
		fa[x]=y;
	}
	void dfs(rg int now,rg int rt){
		dsu.fa[now]=rt;
		if(ch[now][0]) dfs(ch[now][0],rt);
		if(ch[now][1]) dfs(ch[now][1],rt);
	}
	void ad(rg int x,rg int y){
		x=dsu.zhao(x),y=dsu.zhao(y);
		if(x==y) return;
		if(findroot(x)!=findroot(y)){
			link(x,y);
		} else {
			split(x,y);
			dfs(y,y);
		}
	}
}lct;
int n,m,q,x[maxn],y[maxn];
int op[maxn],op1[maxn],op2[maxn],jud[maxn],ans[maxn];
std::map<std::pair<int,int>,int> mp;
int main(){
	n=read(),m=read(),q=read();
	for(rg int i=1;i<=m;i++){
		x[i]=read(),y[i]=read();
		if(x[i]>y[i]) std::swap(x[i],y[i]);
		mp[std::make_pair(x[i],y[i])]=i;
	}
	rg char ch;
	for(rg int i=1;i<=q;i++){
		scanf(" %c",&ch);
		op1[i]=read(),op2[i]=read();
		if(op1[i]>op2[i]) std::swap(op1[i],op2[i]);
		if(ch=='Z'){
			op[i]=1;
			jud[mp[std::make_pair(op1[i],op2[i])]]=1;
			op1[i]=mp[std::make_pair(op1[i],op2[i])];
		} else {
			op[i]=2;
		}
	}
	dsu.init();
	for(rg int i=1;i<=m;i++){
		if(!jud[i]){
			lct.ad(x[i],y[i]);
		}
	}
	for(rg int i=q;i>=1;i--){
		if(op[i]==1){
			lct.ad(x[op1[i]],y[op1[i]]);
		} else {
			if(dsu.zhao(op1[i])==dsu.zhao(op2[i])) ans[i]=1;
		}
	}
	for(rg int i=1;i<=q;i++){
		if(op[i]==2){
			if(ans[i]) printf("Yes\n");
			else printf("No\n");
		}
	}
	return 0;
}

B. 三元组

分析

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define rg register
inline int read(){
	rg int x=0,fh=1;
	rg char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=2e6+5,mod=1e9+7;
inline int addmod(rg int now1,rg int now2){
	return now1+=now2,now1>=mod?now1-mod:now1;
}
inline int mulmod(rg long long now1,rg int now2){
	return now1*=now2,now1>=mod?now1%mod:now1;
}
int t,n,ans,suml[maxn],sumr[maxn],m,cfl1[maxn],cfl2[maxn],cfr1[maxn],cfr2[maxn],f[maxn];
char s1[maxn],s[maxn];
void adl(rg int l,rg int r,rg int a0,rg int d){
	cfl1[l+1]=addmod(cfl1[l+1],d);
	cfl1[r+1]=addmod(cfl1[r+1],mod-d);
	cfl2[l]=addmod(cfl2[l],a0);
	cfl2[r+1]=addmod(cfl2[r+1],mod-a0);
	cfl2[r+1]=addmod(cfl2[r+1],mod-mulmod(r-l,d));
}
void adr(rg int l,rg int r,rg int a0,rg int d){
	cfr1[l+1]=addmod(cfr1[l+1],d);
	cfr1[r+1]=addmod(cfr1[r+1],mod-d);
	cfr2[l]=addmod(cfr2[l],a0);
	cfr2[r+1]=addmod(cfr2[r+1],mod-a0);
	cfr2[r+1]=addmod(cfr2[r+1],mod-mulmod(r-l,d));
}
void solve(){
	memset(suml,0,sizeof(suml));
	memset(sumr,0,sizeof(sumr));
	memset(f,0,sizeof(f));
	memset(cfl1,0,sizeof(cfl1));
	memset(cfl2,0,sizeof(cfl2));
	memset(cfr1,0,sizeof(cfr1));
	memset(cfr2,0,sizeof(cfr2));
	ans=0;
	m=n*2+1;
	s[0]='$';
	for(rg int i=1;i<=m;i++){
		if(i&1) s[i]='#';
		else s[i]=s1[i>>1];
	}
	for(rg int i=1,mids=0,r=0;i<=m;i++){
		if(i<=r) f[i]=std::min(f[2*mids-i],r-i+1);
		while(s[i+f[i]]==s[i-f[i]]) f[i]++;
		if(i+f[i]-1>r) r=i+f[i]-1,mids=i;
	}
	for(rg int i=1;i<=m;i++) f[i]--;
	for(rg int i=1;i<=m;i++){
		if(!f[i]) continue;
		if(i&1){
			adl(i/2+1,i/2+1+f[i]/2-1,i/2,mod-1);
			adr(i/2-f[i]/2+1,i/2,i/2+f[i]/2,mod-1);
		} else {
			if(f[i]>1){
				adl(i/2+1,i/2+f[i]/2,i/2-1,mod-1);
				adr(i/2-(f[i]/2),i/2-1,i/2+f[i]/2,mod-1);
			}
		}
	}
	for(rg int i=1;i<=n;i++) cfl1[i]=addmod(cfl1[i-1],cfl1[i]),cfr1[i]=addmod(cfr1[i-1],cfr1[i]);
	for(rg int i=1;i<=n;i++) cfl2[i]=addmod(cfl2[i],cfl1[i]),cfr2[i]=addmod(cfr2[i],cfr1[i]);
	for(rg int i=1;i<=n;i++) cfl2[i]=addmod(cfl2[i-1],cfl2[i]),cfr2[i]=addmod(cfr2[i-1],cfr2[i]);
	for(rg int i=1;i<=n;i++) cfl2[i]=addmod(cfl2[i],i),cfr2[i]=addmod(cfr2[i],i);
	for(rg int i=1;i<n;i++) ans=addmod(ans,mulmod(cfl2[i],cfr2[i+1]));
	printf("%d\n",ans);
}
int main(){
	t=read();
	while(t--){
		scanf("%s",s1+1);
		n=strlen(s1+1);
		solve();
	}
	return 0;
}

C. 最有价值

分析

最大权闭合子图

先把所有的贡献加起来

对于每一组 \((i,j)\) 新开一个点

由源点向这个点连收益为 \(w_{i,j}+w_{j,i}\) 的点

由这个点向 \(i\) 代表的点和 \(j\) 代表的点连无穷大的边,表示强制选

由每一个位置向它所属的数字连无穷大的边,代表强制选数字

向汇点连边权为 \(a[i]\) 的边

由每一种数字向汇点连边权为 \(b[i]-a[i]\) 的边

用总贡献减去最小割就行了

代码

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstring>
#include<map>
#define rg register
inline int read(){
	rg int x=0,fh=1;
	rg char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') fh=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*fh;
}
const int maxn=2e4+5,maxm=105;
int h[maxn],h2[maxn],tot=2,s,t,n,m,w[maxm][maxm];
struct asd{
	int to,nxt,val;
}b[maxn*20];
void ad(rg int aa,rg int bb,rg int cc){
	b[tot].to=bb;
	b[tot].nxt=h[aa];
	b[tot].val=cc;
	h[aa]=tot++;
}
int q[maxn],head,tail,dep[maxn],mmax;
bool bfs(){
	for(rg int i=1;i<=mmax;i++){
		h[i]=h2[i];
		dep[i]=0;
	}
	q[head=tail=1]=s;
	dep[s]=1;
	while(head<=tail){
		rg int now=q[head++];
		for(rg int i=h[now];i!=-1;i=b[i].nxt){
			rg int u=b[i].to;
			if(b[i].val && !dep[u]){
				dep[u]=dep[now]+1;
				q[++tail]=u;
			}
		}
	}
	return dep[t]!=0;
}
int dfs(rg int now,rg int ac1){
	if(now==t) return ac1;
	rg int ac2=0;
	for(rg int i=h[now];i!=-1;i=b[i].nxt){
		h[now]=i;
		rg int u=b[i].to;
		if(b[i].val && dep[u]==dep[now]+1){
			rg int nans=dfs(u,std::min(b[i].val,ac1));
			b[i].val-=nans;
			b[i^1].val+=nans;
			ac1-=nans;
			ac2+=nans;
		}
		if(ac1==0) break;
	}
	if(ac2==0) dep[now]=0;
	return ac2;
}
int ans=0,T,wa[maxn],wb[maxn];
char ss[maxn];
int main(){
	T=read();
	while(T--){
		memset(h,-1,sizeof(h));
		tot=2,ans=0;
		n=read();
		scanf("%s",ss+1);
		s=1,t=2,mmax=n+2;
		for(rg int i=0;i<=9;i++) wa[i]=read(),wb[i]=read();
		for(rg int i=1;i<=n;i++){
			for(rg int j=1;j<=n;j++){
				w[i][j]=read();
				if(i!=j) ans+=w[i][j];
			}
		}
		for(rg int i=1;i<=n;i++){
			ad(i+2,ss[i]-'0'+1+mmax,0x3f3f3f3f);
			ad(ss[i]-'0'+1+mmax,i+2,0);
		}
		for(rg int i=0;i<=9;i++){
			ad(i+1+mmax,t,wb[i]-wa[i]);
			ad(t,i+1+mmax,0);
		}
		for(rg int i=1;i<=n;i++){
			ad(i+2,t,wa[ss[i]-'0']);
			ad(t,i+2,0);
		}
		mmax+=10;
		for(rg int i=1;i<=n;i++){
			for(rg int j=i+1;j<=n;j++){
				mmax++;
				ad(s,mmax,w[i][j]+w[j][i]);
				ad(mmax,s,0);
				ad(mmax,i+2,0x3f3f3f3f);
				ad(i+2,mmax,0);
				ad(mmax,j+2,0x3f3f3f3f);
				ad(j+2,mmax,0);
			}
		}
		for(rg int i=1;i<=mmax;i++) h2[i]=h[i];
		while(bfs()) ans-=dfs(s,0x3f3f3f3f);
		printf("%d\n",ans);
	}
	return 0;
}

标签:ch,14,省选,int,rg,maxn,测试,include,mod
来源: https://www.cnblogs.com/liuchanglc/p/14359138.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有