【超好懂的比赛题解】The 2019 ICPC Asia Nanjing Regional Contest 比赛题解

57 篇文章 0 订阅
38 篇文章 0 订阅

title : The 2019 ICPC Asia Nanjing Regional Contest
date : 2022-7-29
tags : ACM,题解,练习记录
author : Linno


2019 ICPC区域赛南京站题解

题目链接:https://codeforces.com/gym/103466

补题进度:8/11

A - A Hard Problem

//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;

//int read(){ int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
//  freopen("in.cpp","r",stdin);
//  freopen("out.cpp","w",stdout);
	int T=1,n;
	cin>>T;
// clock_t start,finish;
// start=clock();
	while(T--) {
		cin>>n;
		if(n&1) cout<<(n+1)/2+1<<"\n";
		else cout<<n/2+1<<"\n";
	}
// finish=clock();
// cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
	return 0;
}

C - Digital Path

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a[1005][1005],visit[1005][1005],f[1005][1005][5],ans,cnt;
const long long mod=1000000007;
const long long dx[5]= {0,-1,1,0,0};
const long long dy[5]= {0,0,0,-1,1};
struct dat {
	int val,x,y;
} b[1000005];
void dfs(int x,int y,int k) {
	visit[x][y]=1;
	int xx=0,yy=0,flag=0;
	for (int i=1; i<=4; ++i) {
		xx=x+dx[i];
		yy=y+dy[i];
		if (xx<1||yy<1||xx>n||yy>m||a[xx][yy]-k!=1) continue;
		if (!visit[xx][yy]) dfs(xx,yy,k+1);

		f[x][y][4]+=f[xx][yy][3]+f[xx][yy][4];
		f[x][y][4]%=mod;
		f[x][y][3]+=f[xx][yy][2];
		f[x][y][3]%=mod;
		f[x][y][2]+=f[xx][yy][1];
		f[x][y][2]%=mod;
		flag=1;
	}
	if (flag==0) f[x][y][1]=1;
}
bool cmp(dat a,dat b) {
	return a.val<b.val;
}
signed main() {
	cin>>n>>m;
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j) {
			scanf("%lld",&a[i][j]);
			b[++cnt].val=a[i][j];
			b[cnt].x=i;
			b[cnt].y=j;
		}
	sort(b+1,b+1+cnt,cmp);
	for (int i=1; i<=cnt; ++i) {
		int x=b[i].x;
		int y=b[i].y;
		if (!visit[x][y]) {
			dfs(x,y,a[x][y]);
			ans+=f[x][y][4];
			ans%=mod;
		}
	}
	cout<<ans;
	return 0;
}

H - Prince and Princess

//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;

//int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
void Solve() {
	int a,b,c;
	cin>>a>>b>>c;
	if(a==1&&!b&&!c) {
		cout<<"YES\n";
		cout<<"0\n";
	} else if(b+c>=a) { //假话和真话至少一样多,没办法判断
		cout<<"NO\n";
	} else { //假定所有随机回答都是假话,那么我们还得再问多一个人才能得到答案
		cout<<"YES\n";
		cout<<2*(b+c)+1<<"\n";
	}
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
//  freopen("in.cpp","r",stdin);
//  freopen("out.cpp","w",stdout);
	int T=1;
//	cin>>T;
//	clock_t start,finish;
//	start=clock();
	while(T--) {
		Solve();
	}
//	finish=clock();
//	cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
	return 0;
}

K - Triangle

#include<bits/stdc++.h>
using namespace std;
const double esp=1e-8;
typedef long long ll;
struct pp {
	double x,y;
} pps[4];
pp ppt;
inline void read(int &x) { //整型快读,注意这里是void有自变量
	x=0;
	char c=getchar();
	for (; !isdigit(c); c=getchar());
	for (; isdigit(c); c=getchar()) x=x*10+c-'0';
}
inline bool check1(int i,int j) {
	if(fabs((pps[i].y-ppt.y)*(pps[j].x-ppt.x)-(pps[j].y-ppt.y)*(pps[i].x-ppt.x))<esp) {
		double xx1=max(pps[i].x,pps[j].x);
		double xx2=min(pps[i].x,pps[j].x);
		double yy1=max(pps[i].y,pps[j].y);
		double yy2=min(pps[i].y,pps[j].y);
		if(((ppt.x-xx2)>-esp)&&((xx1-ppt.x)>-esp)&&((ppt.y-yy2)>-esp)&&((yy1-ppt.y)>-esp))
			return true;
	}
	return false;
}
inline double bian2(int i,int j) {
	return (pps[i].x-pps[j].x)*(pps[i].x-pps[j].x)+(pps[i].y-pps[j].y)*(pps[i].y-pps[j].y);
}
inline void midd(int i,int j) {
	printf("%.7lf %.7lf\n",(pps[i].x+pps[j].x)/2.0,(pps[i].y+pps[j].y)/2.0);
}
int main () {
	int t;
	read(t);
	int x,y;
	while(t--) {
		for(int i=0; i<=2; ++i) {
			read(x);
			read(y);
			pps[i].x=x;
			pps[i].y=y;
		}
		read(x);
		read(y);
		ppt.x=x;
		ppt.y=y;
		pps[3].x=ppt.x;
		pps[3].y=ppt.y;
		bool f=0;
		int kk=0;
		for(int i=0; i<=2; ++i) {
			if(check1(i,(i+1)%3)) {
				f=1;
				kk=i;
				break;
			}
		}
		//cout<<kk<<endl;
		if(!f) {
			puts("-1");
			continue;
		}
		double s1=bian2(kk,(kk+1)%3);
		double s2=bian2(kk,(kk+2)%3);
		double ss=bian2(kk,3);
		if(fabs(ss)<esp) {
			midd((kk+1)%3,(kk+2)%3);
			continue;
		}
		if(fabs(ss-s1)<esp) {
			midd((kk+2)%3,kk);
			continue;
		}
		double ss1=(s1*s2)/(4.0*ss);
		if((sqrt(s2)-sqrt(ss1))>-esp) {
			double k1=sqrt(ss1/s2);
			printf("%.7lf %.7lf\n",pps[kk].x+k1*(pps[(kk+2)%3].x-pps[kk].x),pps[kk].y+k1*(pps[(kk+2)%3].y-pps[kk].y));
			continue;
		} else {
			double ssk=bian2(3,(kk+1)%3);
			double ssk1=bian2((kk+1)%3,(kk+2)%3);
			double ss2=(s1*ssk1)/(4.0*ssk);
			if((sqrt(ssk1)-sqrt(ss2))>-esp) {
				double k2=sqrt(ss2/ssk1);
				printf("%.7lf %.7lf\n",pps[(kk+1)%3].x+k2*(pps[(kk+2)%3].x-pps[(kk+1)%3].x),pps[(kk+1)%3].y+k2*(pps[(kk+2)%3].y-pps[(kk+1)%3].y));

				continue;
			} else puts("-1");
		}
	}
	return 0;
}

J - Spy

//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 2e18
#define int __int128
//#define int long long
using namespace std;
const int N=2007;
int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}

int n,ans=0,a[N],p[N],c[N],d[N],match[N],minz;
int sum[N],vis[N],lx[N],ly[N],mp[N][N],pre[N],slack[N],idx=0;

//bool cmp(int A,int B){return a[A]<a[B];}

void bfs(int u){
	int x,y=0,yy=1;  
	memset(pre,0,sizeof(pre)); //清空前驱 
	for(int i=1;i<=n;i++) slack[i]=inf;
	match[y]=u; //出发点的配对设为u 
	while(1){
		x=match[y]; //获取y当前匹配的左部点
		minz=inf; //松弛量 
		vis[y]=idx; //本轮已经访问过y点 
		for(int i=1;i<=n;i++){
			if(vis[i]==idx) continue; //已经访问过了 
			if(slack[i]>lx[x]+ly[i]-mp[x][i]){ 
				slack[i]=lx[x]+ly[i]-mp[x][i];
				pre[i]=y; //记录i的前驱 
			}
			if(slack[i]<minz){
				minz=slack[i]; //记录最小松弛量 
				yy=i; //记录来源 
			}
		}
		for(int i=0;i<=n;i++){
			if(vis[i]==idx){ //本轮参与匹配 	
				lx[match[i]]-=minz;
				ly[i]+=minz;	//更新顶标 
			}else{
				slack[i]-=minz; //更新其他点的松弛量 
			}
		}
		y=yy; //替换出发点 
		if(!match[y]) break; //如果无法匹配了,跳出
	}
	while (y){  //根据增广路记录配对 
		match[y]=match[pre[y]]; 
		y=pre[y];
	}
}

int KM(){  //EK求最大权匹配 
	for(int i=1;i<=n;i++){
		idx++; //时间戳代替memset 
		bfs(i);
	}
	int res=0; //记录答案 
	for(int i=1;i<=n;i++){
		if(match[i]){
			res+=mp[match[i]][i];  
		}
	}
	return res;
}

void Solve(){
	n=read();//cin>>n;
	for(int i=1;i<=n;++i) a[i]=read();//cin>>a[i];
	for(int i=1;i<=n;++i) p[i]=read();//cin>>p[i];
	for(int i=1;i<=n;++i) c[i]=read();//cin>>c[i];
	for(int i=1;i<=n;++i) d[i]=read();//cin>>d[i];
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			for(int k=1;k<=n;++k){
				if(c[i]+d[j]>a[k]) mp[i][j]+=p[k];
			}
		}
	}
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j){
			lx[i]=max(lx[i],mp[i][j]); //顶标预处理 
		}
	}
	write(KM());putchar('\n');
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
//  freopen("in.cpp","r",stdin);
//  freopen("out.cpp","w",stdout);
	int T=1;
//	cin>>T;
//	clock_t start,finish;
//	start=clock();
	while(T--){
		Solve();
	}
//	finish=clock();
//	cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
	return 0;
}

B - Chessboard

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline void read(int &x) { //整型快读,注意这里是void有自变量
	x=0;
	char c=getchar();
	for (; !isdigit(c); c=getchar());
	for (; isdigit(c); c=getchar()) x=x*10+c-'0';
}
const int mod=1e9+7;
inline ll qpow(ll a, ll b) {
	ll ans=1;
	while(b) {
		if(b&1) {
			ans=(ans*a)%mod;
		}
		a=(a*a)%mod;
		b>>=1;
	}
	return ans;
}
ll fac[2000050];

ll dp[450][450];
ll a[450],b[450],c[450],p[450];
ll n;
int main () {
	fac[0]=1;
	for(int i=1; i<=2e6+2; ++i) {
		fac[i]=(fac[i-1]*i)%mod;
	}
	int t;
	read(t);
	int n,m;
	while(t--) {
		read(n);
		read(m);
		if(n>m) {
			int t=m;
			m=n;
			n=t;
		}
		if(n==1) {
			if(m==1) {
				printf("1\n");
			} else printf("2\n");
		} else {
			ll kk=(fac[n+m-2]*qpow(fac[n-1],mod-2))%mod*qpow(fac[m-1],mod-2)%mod;
			kk=(4ll*kk)%mod;
			printf("%lld\n",kk);
		}
	}
	return 0;
}

I - Space Station

//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define int long long
#define base 131
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;
typedef unsigned long long ull;
//int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}

int n,mx=0,a[N],frac[N],cnt[55];
unordered_map<ull,int>dp;  //用每个数出现次数的哈希值做记忆化

inline int dfs(int eng,int stp) { //已经选了stp个数,目前已有的体力eng
	if(!stp) return 1;
	if(eng>=mx) {
		return frac[stp];
	}
	ull hs=0,ans=0;
	for(int i=50; i>=0; --i) hs=hs*base+cnt[i];
	if(dp.find(hs)!=dp.end()) return dp[hs];
	for(int i=1; i<=eng; ++i) {
		if(cnt[i]) {
			--cnt[i];
			ans+=(cnt[i]+1)*dfs(min(mx,eng+i),stp-1)%mod;
			ans%=mod;
			++cnt[i];
		}
	}
	return dp[hs]=ans;
}

void Solve() {
	cin>>n>>a[0];
	frac[0]=1;
	for(int i=1; i<=n; ++i) frac[i]=frac[i-1]*i%mod;
	int ans,zero=0;
	for(int i=1; i<=n; ++i) {
		cin>>a[i];
		++cnt[a[i]];
		mx=max(a[i],mx);
		if(!a[i]) ++zero;
	}
	ans=dfs(a[0],n-zero); //搜索的时候去掉a[i]=0的点
	for(int i=n; i>=n-zero+1; --i) ans=ans*i%mod; //最后乘上可以插在任意位置的0
	cout<<ans<<"\n";
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
//  freopen("in.cpp","r",stdin);
//  freopen("out.cpp","w",stdout);
	int T=1;
//	cin>>T;
//	clock_t start,finish;
//	start=clock();
	while(T--) {
		Solve();
	}
//	finish=clock();
//	cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
	return 0;
}

F - Paper Grading

//#pragma GCC optimize("Ofast", "inline", "-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
#define lb(x) (x&(-x))
#define mid ((l+r)>>1)
using namespace std;
const int N=2e5+7;
const int mod=1e9+7;

//int read(){	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
//void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}
int n,m;
int tot=1,idx=0,trie[N][26],ed[N],id[N],dfn[N];
int sz[N],root[N];
char str[N];

struct node {
	int ls,rs,num;
} tr[N<<5];

void insert(int i) { //插入字符串
	int now=1,len=strlen(str);
	for(int i=0; i<len; ++i) {
		if(!trie[now][str[i]-'a']) trie[now][str[i]-'a']=++tot;
		now=trie[now][str[i]-'a'];
	}
	ed[i]=now;  //字符串结束点
}

void dfs(int i) { //在trie上处理dfs序
	dfn[++idx]=i;
	id[i]=idx;
	sz[i]=1;
	for(int j=0; j<26; ++j) {
		if(trie[i][j]) {
			dfs(trie[i][j]);
			sz[i]+=sz[trie[i][j]];
		}
	}
}

void update(int &rt,int l,int r,int pos,int w) {
	if(!rt) rt=++tot;
	tr[rt].num+=w;
	if(l==r) return;
	if(pos<=mid) update(tr[rt].ls,l,mid,pos,w);
	else update(tr[rt].rs,mid+1,r,pos,w);
}

int query(int rt,int l,int r,int ql,int qr) {
	if(!rt) return 0;
	if(ql<=l&&r<=qr) return tr[rt].num;
	int ans=0;
	if(ql<=mid) ans+=query(tr[rt].ls,l,mid,ql,qr);
	if(qr>mid) ans+=query(tr[rt].rs,mid+1,r,ql,qr);
	return ans;
}

inline void add(int x,int pos,int w) {
	for(; x<=n; x+=lb(x)) update(root[x],1,idx,pos,w);
}

inline ask(int x,int l,int r) {
	int ans=0;
	for(; x; x-=lb(x)) ans+=query(root[x],1,idx,l,r);
	return ans;
}

inline int get(int k) {
	int now=1;
	for(int i=0; i<k; ++i) {
		if(trie[now][str[i]-'a']) now=trie[now][str[i]-'a'];
		else return 0;
	}
	return now;
}

void Solve() {
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; ++i) {
		scanf("%s",str);
		insert(i);
	}
	dfs(1);
	tot=0;
	for(int i=1; i<=n; ++i) add(i,id[ed[i]],1);
	for(int i=1,op,k,l,r; i<=m; ++i) {
		scanf("%d",&op);
		if(op==1) {
			scanf("%d%d",&l,&r);
			add(l,id[ed[l]],-1);
			add(l,id[ed[r]],1);
			add(r,id[ed[l]],1);
			add(r,id[ed[r]],-1);
			swap(ed[l],ed[r]);
		} else {
			scanf("%s",str);
			scanf("%d%d%d",&k,&l,&r);
			k=get(k);
			if(!k) printf("0\n");
			else printf("%d\n",ask(r,id[k],id[k]+sz[k]-1)-ask(l-1,id[k],id[k]+sz[k]-1));
		}
	}
}

signed main() {
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
//  freopen("in.cpp","r",stdin);
//  freopen("out.cpp","w",stdout);
	int T=1;
//	cin>>T;
//	clock_t start,finish;
//	start=clock();
	while(T--) {
		Solve();
	}
//	finish=clock();
//	cerr<<((double)finish-start)/CLOCKS_PER_SEC<<endl;
	return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RWLinno

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值