2019 Petrozavodsk Winter Camp, Yandex Cup 解题报告

H


签到题,每行最小值的最大值就是答案。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

int n;
ll Ans,tmp;

int main(){
	n=input();
	for(int i=1;i<=n;i++){
		tmp=0x3f3f3f3f;
		for(int j=1;j<=n;j++)
			tmp=min(tmp,input());
		Ans=max(tmp,Ans);
	}
	printf("%lld\n",Ans);
}

A


贪心,每次选择增量最小的点。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

#define PII pair<int,int>
#define fr first
#define sc second
#define mp make_pair

const int N=3e5+7;

struct node{
	int x,y;
	int id;
	bool operator <(const node &t)const{
		return x+y>t.x+t.y;
	}
}a[N];

int n;

priority_queue <node> Q;

int main(){
	n=input();
	for(int i=1;i<=n;i++){
		a[i].x=input(),a[i].y=input();
		a[i].id=i;
		Q.push(a[i]);
	}

	int x=1,y=1;

	while(!Q.empty()){
		node t=Q.top();Q.pop();
		if(x>t.x){
			t.x=x;
			Q.push(t);
			continue;
		}
		if(y>t.y){
			t.y=y;
			Q.push(t);
			continue;
		}

		printf("%d%c",t.id,Q.empty()? '\n':' ');
		x=max(x,t.x),y=max(t.y,y);
	}
}

J


往左右试探,每次倍增4倍(因为要在30m内解决问题)当走到1时分别执行一次+和-,就很简单的知道答案是什么了。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

int main(){
	char c='+';
	int len=1,check;
	while(1){
		for(int i=1;i<=len;i++){
			cout<<c<<endl;
			cin>>check;
			if(check){
				cout<<'+'<<endl;
				cin>>check;
				cout<<'-'<<endl;
				cin>>check;
				if(check) cout<<"! ugly"<<endl;
				else if(c=='+') cout<<"! bad"<<endl;
				else cout<<"! good"<<endl;
				return 0;
			}
		}
		c='+'+'-'-c;
		len*=4;
	}
}

I


把"^>v<"分别设为0、1、2、3,那么操作不会改变棋盘和(mod 4)。我们可以根据L和R构造一个二分图,那么答案肯定就是二分图匹配。如果没有匹配完所有的棋盘(有剩余的位置),那么我们一定能利用这个剩余的位置来对别的位置进行操作,使得匹配都能贡献答案。这个时候答案就是匹配数。如果匹配完了所有的棋盘,我们猜想如果棋盘和(mod 4)满足条件,那么答案也是匹配数。否则我们一定要拆开一对拖鞋,答案是匹配数减去 1。

摘自:http://clatisus.com/Petrozavodsk Winter-2019. Yandex Cup-2019#i.-slippers


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
	ll x=0,f=0;char ch=getchar();
	while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return f? -x:x;
}

const int N=105;
const int M=10005;

#define pb push_back

vector<int> G[M];
int match[M],vis[M];
int n,m,cnt;
int id[N][N],type[N][N],mp[N][N];
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int Ans;

bool dfs(int u){
	for(auto v:G[u]){
		if(vis[v]!=vis[0]){
			vis[v]=vis[0];
			if(!match[v]||dfs(match[v])){
				match[v]=u,match[u]=v;
				return 1;
			}
		}
	}
	return 0;
}

int main(){
	n=input(),m=input();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			id[i][j]=++cnt;

	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char s[3];
			scanf("%s",s);
			if(s[1]=='^') mp[i][j]=0;
			if(s[1]=='>') mp[i][j]=1;
			if(s[1]=='v') mp[i][j]=2;
			if(s[1]=='<') mp[i][j]=3;
			if(s[0]=='R') type[i][j]=1; 
		}
	}

	for(int x=1;x<=n;x++){
		for(int y=1;y<=m;y++){
			if(!type[x][y]){
				for(int k=0;k<=3;k++){
					int tx=x+dx[k],ty=y+dy[k];
					if(tx<1||tx>n||ty<1||ty>m||!type[tx][ty]) continue;
					G[id[x][y]].pb(id[tx][ty]);
					G[id[tx][ty]].pb(id[x][y]);
				}
				vis[0]++;
				Ans+=dfs(id[x][y]);
			}
		}
	}
	if(Ans*2!=n*m){
		printf("%d\n",Ans);
	}else{
		int sum=0;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(type[i][j]){
					int nx=match[id[i][j]];
					int ti=(nx-1)/m+1,tj=(nx-1)%m+1;
					// cout<<i<<' '<<j<<' '<<ti<<' '<<tj<<endl;
					sum+=mp[i][j],sum+=mp[ti][tj];
					for(int k=0;k<=3;k++)
						if(i==ti+dx[k]&&j==tj+dy[k])
							sum-=2*(k+1);
				}
			}
		}
		// printf("%d\n",sum);
		if(sum%4) Ans--;
		printf("%d\n",Ans);
	}
}
posted @ 2020-04-16 21:00  _aether  阅读(380)  评论(0编辑  收藏  举报