7.10 18级多校适应训练1题解(The 2019 Southeastern Europe Regional Contest)

7.10 18级多校适应训练1题解(The 2019 Southeastern Europe Regional Contest)

比赛过程

一开始上来看A题,lzp写A,开始看B,B没看太懂。有队伍出了I题,发现I是签到题。之后Evelyn看D,uin看C,有队伍了过了D,转手做D,后面也是跟着做J和F,但是F整体思路错了,所以没有做出来。
发现问题是,自己不能选择做题,陷入坑里。

题解

D Cycle String?

题目链接

题意

题目中给出一个长度为\(\,2*n\,\)的字符串,要求对该字符串的字符进行重新排列,保证任意长度为\(\,n\,\)的子串(连续字符)都是不相同的

解法

通过分析发现,总共需要分多种情况:
1 所有出现过的字符次数都小于\(\,n\,\),直接按字典序输出即可
2 如果有字符的次大于\(\,n\,\),需要分以下几种情况:
1 ) 如果出现字符个数为\(\,1\,\) 一定为NO
2 ) 如果出现字符个数为2 讨论较少个数字符的数量即可,如果>=3就是YES ,否则NO
3 ) 如果出现字符个数为3 首先输出\(\,n\,\)个最多字符,然后输出一个其他任意字符,然后继续输出剩下的那个最多的字符,其余的字符按照字典序输出即可

代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
	string s;
	cin>>s;
	int len=s.length();
	int c[26];
	memset(c,0,sizeof(c));
	int judge=0;
	int cnt=0,big=-1;
	for(int i=0;i<len;i++){
		if(c[s[i]-'a']==0)cnt++;
		c[s[i]-'a']++;
		if(judge==0&&c[s[i]-'a']>(len/2)){
			big=s[i]-'a';
			judge=1;
		}
	}
	int n=len/2;
//	cout<<n<<endl;
	if(judge==1){
		if(cnt==1)
		cout<<"NO"<<endl;
		else if(cnt==2){
			if(n+n-c[big]>=3){	
				int last=n+n-c[big]-1;
				cout<<"YES"<<endl;
				int x=0;
				for(int i=0;i<26;i++){
					if(c[i]>0&&i!=big){
						x=i;break;
					}
				}
				for(int i=1;i<=n;i++){
					cout<<char('a'+big);
				}
				c[big]-=n;
				cout<<char('a'+x);
				
				while(c[big]--)cout<<char('a'+big);
				while(last--)cout<<char('a'+x);
			}else{
				cout<<"NO"<<endl;
			}
		}else if(cnt>=3){
			cout<<"YES"<<endl;

			
			int x=0;
			for(int i=0;i<26;i++){
				if(c[i]>0&&i!=big){
					x=i;break;
				}
			}
			for(int i=1;i<=n;i++){
				cout<<char('a'+big);
			}
			c[big]-=n;
			cout<<char('a'+x);
			c[x]--;
			while(c[big]--)cout<<char('a'+big);
		//	cout<<"bug"<<c[2]<<endl;
			for(int i=0;i<26;i++){
				if(c[i]<=0)continue;
				while(c[i]--){
				//	cout<<c[i];
					cout<<char('a'+i);
				}	
			}cout<<endl;
			
		}
		return 0;
	}else{
		cout<<"YES"<<endl;
		for(int i=0;i<26;i++){
			while(c[i]--){
				cout<<char('a'+i);
			}	
		}cout<<endl;
		
	}	
	
	
	
}

I Absolute Game

题目链接

题意

Alice和Bob两个老博弈家玩游戏。Alice和Bob都有\(\,n\,\)个牌,且互相知道牌的大小,依次轮流(Alice先手)每个人丢出一张牌,最后各剩下一张牌A和B。Alice想让两个牌的差值\(\,|A-B|\,\)尽量大,Bob想让差值尽量小,两人足够聪明,求解最后的差值是多少。

解法

因为不管Alice丢掉哪张牌,Bob都会留下差值尽量小的牌。对Alice的每张牌,用Bob的每张牌来求差值,取每一组的最小值,得到一组最小值。最后取这一组的最大值。

代码

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
using namespace std;
#define IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int inf = 0x3f3f3f3f;
typedef long long ll;
const int maxn = 100500;
const ll mod = 1e9 + 7;
typedef pair<int,int> pii;
ll a[1050],b[1050];
ll ans = 0;
int main() {
    IO;
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=n;i++)
		cin>>b[i];
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++) {
		ll cnt=inf;
		for(int j=1;j<=n;j++)
			cnt = min(abs(b[j]-a[i]),cnt);
		ans = max(ans,cnt);
	}
	cout<<ans<<endl;
	return 0;
}

J Graph and Cycles

题目链接

题意

给定一个\(\,n\,\)\(\,n\,\)为奇数)的无向完全图,分出任意(注意:任意)个圈,任意两个圈没有重合的边,而且每一条边只属于一个圈内。对于每个圈的每个顶点相连的两条边取最大值相加作为这个圈的权重。求解所有圈的权重最小是多少。

解法

一开始看样例,觉得可能只能那样,但是理解题意后就是自己找出最优方案就可以,有可能会有多个方案的结果是一样的。到这里会有一种错觉,跟I题签到题如出一辙(I题是最小值里面找最大),这题是(最大值里面变最小)。抛开题面,假如有n组四个值,有某种规则的求每组4个值找两个数最大值最小化,就是排序让第1大和第3大相加。回归题面,不管是怎样的组合,1个顶点的2条边在哪个圈里,不妨碍求值。确定一个顶点和一组边,“牵连着”确定另一个顶点和另一条边。

定义 \(\,ans = 0\,\),对每个顶点的\(\,n-1\,\)条边从小到大排序,把\(\,max(1,2),max(3,4),max(5,6),...,max(n-2,n-1)\,\)条边的权重加在 \(\,ans\,\) 里面即可。

代码

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <limits>
#include <list>
#include <map>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <utility>
#include <vector>
#include <cwchar>
#include <cwctype>
using namespace std;
#define IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int inf = 0x3f3f3f3f;
typedef long long ll;
const int maxn = 1500;
const ll mod = 1e9 + 7;
typedef pair<int,int> pii;
struct Point{
    ll v, w;
    Point(ll v, ll w): v(v), w(w) {}
};
bool cmp(Point A,Point B) {
    return A.w<B.w;
};
vector<vector<Point> > G(maxn);
int main() {
    IO;
    int n;
    cin>>n;
    for(int i=0;i<n*(n-1)/2;i++){
        ll u,v,w;
        cin>>u>>v>>w;
        G[u].push_back(Point(v, w));
        G[v].push_back(Point(u, w));
    }
    for(int i=1; i<=n ;i++)
        sort(G[i].begin(),G[i].end(),cmp);
    ll ans = 0;
    for(int i=1; i<=n ;i++)
        for(int j=0; j<(n-1)/2 ;j++){
            ll ans1=G[i][2*j].w;
            ll ans2=G[i][2*j+1].w;
            ans+=max(ans1, ans2);
        }
    cout<<ans<<endl;

    return 0;
}
posted @ 2020-07-12 00:23  cugbacm03  阅读(116)  评论(0)    收藏  举报