2019-2020 ICPC Southeastern European Regional Programming Contest (SEERC 2019)

今天打了一下SEERC2019,雖然做的很菜,但是題的質量真的不錯

I 簽到題(思維)

題意:

Alice和Bob玩取數遊戲,Alice每次從A序列中取出一個數字,Bob每次從B序列中取出一個數字,兩人輪流取數字,直到最後只剩下一個數字,Alice先手。Alice希望最後剩下的兩個數字差值的絕對值儘可能的小,Bob則相反,問如果兩人都取最佳策略,最後這個絕對值最大是多少?

分析與解答:

因爲兩個人的選取最佳策略,那麼無論Alice最後剩下數字爲多少,Bob一定會取到和它差值最小的那個,因此答案就是max{min{aibj}}max\{min\{a_i-b_j\}\}

代碼:

#include <cstdio>
#include <algorithm>
#define MAXN 1003
#include <cstring>
#include <cmath>
using namespace std;

long long a[MAXN],b[MAXN];
long long ans = 0;
int main()
{
	int n;
	scanf("%d",&n);
	for(int i = 1;i <= n;i++)
		scanf("%I64d",&a[i]);
	for(int i = 1;i <= n;i++)
		scanf("%I64d",&b[i]);
	sort(a + 1,a + 1 + n);
	for(int i = 1;i <= n;i++)
	{
		long long res  = 2e9;
		for(int j = 1;j <= n;j++)
			res = min(abs(b[j] - a[i]),res);
		ans = max(ans,res);
	}
	printf("%I64d\n",ans);
	return 0;
}

D 構造+思維

題意:

給定一個長爲2n2n由小寫字母組成的序列,讓你找出這些字母構成的一個首尾相連的字符串,使得任何一個長度爲nn的子串不重複

分析與解答:

①出現次數最多的字母出現次數小於n,直接按照aabbcca……ab……bc……c……的順序依次排列下去
②出現次數最多的字母出現次數大於nn,這樣的字母最多有一個這時候分爲以下幾類:
①’如果僅有兩種字母,且另一種字母的出現次數小於33,無法構造
②’設次數最多的字母爲aa,先放nnaa,接着放一個其他字母,再把剩下的aa全部放完,後邊的放置方法同①

代碼

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;

string s;
int sum[30],n,tmp;

int main() {
	memset(sum,0,sizeof(sum));
	cin >> s;
	int len = s.length(); n=len/2;
	for (int i=0;i<len;i++) {
		sum[s[i]-'a']++;
	}
	bool flag=true,ltn=false;
	int t=0;
	for (int i=0;i<26;i++) {
		if (sum[i])
			t++;
		if (sum[i]>n) {
			ltn=true;
			tmp=i;
		}
	}
	if (!ltn) {
		printf("YES\n");
		for (int i=0;i<26;i++) {
			for (int j=1;j<=sum[i];j++) {
				printf("%c",i+'a');
			}
		}
	} else {
		if (t==1) {
			printf("NO\n");
		} else if (t==2) {
			if (len-sum[tmp]<=2) {
				printf("NO\n");
			} else {
				printf("YES\n");
				for (int i=1;i<=n;i++) {
					printf("%c",tmp+'a');
				}
				for (int i=0;i<26;i++) {
					if (sum[i] && i!=tmp) {
						printf("%c",i+'a');
						sum[i]--;
						break;
					}
				}
				for (int i=1;i<=sum[tmp]-n;i++) {
					printf("%c",tmp+'a');
				}
				for (int i=0;i<26;i++) {
					if (i!=tmp)
					for (int j=1;j<=sum[i];j++) {
						printf("%c",i+'a');
					}
				}
			}
		} else {
				printf("YES\n");
				for (int i=1;i<=n;i++) {
					printf("%c",tmp+'a');
				}
				for (int i=0;i<26;i++) {
					if (sum[i] && i!=tmp) {
						printf("%c",i+'a');
						sum[i]--;
						break;
					}
				}
				for (int i=1;i<=sum[tmp]-n;i++) {
					printf("%c",tmp+'a');
				}
				for (int i=0;i<26;i++) {
					if (i!=tmp)
						for (int j=1;j<=sum[i];j++) {
							printf("%c",i+'a');
						}
				}
		}
	}
	return 0;
}

J 思維(圖論?)

題目:

給你一個nn爲奇數的完全圖,讓你從中找出一種邊的劃分使得每條邊有且僅屬於一個長度大於22的環中(對於每個環,它的valuevalue值爲相鄰兩條邊取最大權值的和),並且所有環的valuevalue值的和最小,輸出這個最小值。

分析與解答:

我們考慮每個點的對答案的貢獻,對於相鄰的兩條邊來說,它們是靠一個點作爲銜接,也就是說對於一個點來說,與它連接的所有的邊一個是兩兩配對出現在一個環中的,因此答案就是將每個點的各個邊排序,然後兩兩配對,取大的那個權值。

代碼:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define MAXN 1000005
typedef long long ll;
using namespace std;

ll ans=0;
bool vis[MAXN*2];
int tot,n,st;
struct Edge1 {
	int u,v;
	ll w;
}e[MAXN*2];
struct Edge {
	int to,next;
	ll w;
}edge[MAXN*2];
int head[MAXN];
void init() {
	tot=0;
	memset(head,-1,sizeof(head));
	memset(vis,false,sizeof(vis));
}
void addedge(int u, int v, int w) {
	edge[tot].to=v;
	edge[tot].w=w;
	edge[tot].next=head[u];
	head[u]=tot++;
}
bool cmp(Edge1 e1, Edge1 e2) {
	return e1.w<e2.w;
}
int main() {
	init();
	scanf("%d",&n);
	for (int i=1;i<=n*(n-1)/2;i++) {
		scanf("%d%d%lld",&e[i].u,&e[i].v,&e[i].w);
	}
	sort(e+1,e+1+n*(n-1)/2,cmp);
	for (int i=1;i<=n*(n-1)/2;i++) {
		addedge(e[i].u,e[i].v,e[i].w);
		addedge(e[i].v,e[i].u,e[i].w);
	}
	for (int i=1;i<=n;i++) {
		for(int j = head[i];~j;j=edge[j].next)
		{
			ans += edge[j].w;
			j = edge[j].next;
		}
	}
	cout << ans << endl;
	return 0;
}

F

據說是一個樹形dp,待補題

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