Codeforces Round #713 (Div. 3)

比赛链接

Codeforces Round #713 (Div. 3)

C. A-B Palindrome

一句话题意,给出 \(T\) 个由 01? 组成的字符串,以及这个字符串由 \(a\)0\(b\)1 组成,要求将字符串中的 替换成 01 之后是一个回文串并且恰好有 \(a\)0\(b\)1

解题思路

模拟

想复杂了,之前想的是将奇数的情况转换为偶数的情况,然后只用判断偶数的情况。其实完全模拟一遍即可:从左到右对应位置上如果对称的两个字符出现矛盾,则不满足要求,否则按个数填入01,有00否则填1,最后判断合法性即可

  • 时间复杂度:\(O(n)\)

代码

// Problem: C. A-B Palindrome
// Contest: Codeforces - Codeforces Round #713 (Div. 3)
// URL: https://codeforces.com/contest/1512/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}


int main()
{
    int t,a,b;
    for(cin>>t;t;t--)
    {
    	cin>>a>>b;
    	string s;
    	cin>>s;
    	int n=s.size();
    	bool f=false;
    	int ta=0,tb=0;
    	for(int i=0,j=s.size()-1;i<j;i++,j--)
    		if(s[i]=='?'&&s[j]!='?')
    		{
    			s[i]=s[j];
    			if(s[i]=='0')ta+=2;
    			else
    				tb+=2;
    		}
    		else if(s[i]!='?'&&s[j]=='?')
    		{
    			s[j]=s[i];
    			if(s[i]=='0')ta+=2;
				else
					tb+=2;
    		}
    		else if(s[i]!='?'&&s[j]!='?')
    		{
    			if(s[i]!=s[j])
    			{
    				f=true;
    				break;
    			}
    			else
    			{
    				if(s[i]=='0')ta+=2;
    				else
    					tb+=2;
    			}
    		}
    	if(f)
    	{
    		puts("-1");
    		continue;
    	}
    	else
    	{
    		if(n&1)
    		{
    			if(s[n/2]=='0')ta++;
    			else if(s[n/2]=='1')tb++;
    		}
    		if(ta>a||tb>b)puts("-1");
    		else
    		{
    			a-=ta,b-=tb;
    			for(int i=0,j=s.size()-1;i<j;i++,j--)
    				if(s[i]=='?')
    				{
    					if(a>=2)s[i]=s[j]='0',a-=2;
    					else if(b>=2)s[i]=s[j]='1',b-=2;
    					else
    					{
    						f=true;
    						break;
    					}
    				}
    			if(f)puts("-1");
    			else
    			{
    				if(n%2==1&&s[n/2]=='?')
    				{
    					if(a)s[n/2]='0',a--;
    					else if(b)s[n/2]='1',b--;
    				}
    				if(a!=0||b!=0)f=true;
    				for(int i=0;i<n;i++)
    					if(s[i]=='?')f=true;
    				if(f)puts("-1");
    				else
    					cout<<s<<'\n';
    			}
    		}
    	}
    }
    return 0;
}

E. Permutation by Sum

一句话题意: \(T\) 组数据,每组数据由互相独立的 \(n, l, r, s\) 组成,求 \(\{a\} ,\{a\}\) 是 1 到 \(n\) 的一个排列使得 \(\sum_{i=l}^{r} a_{i}=s\) ,并输出这个排列,如果无法找到这样的排列输出 \(-1\)

解题思路

贪心,构造

对于一段连续的区间 \([l,r]\),选取 \(x\) 个数使其和为 \(s\),如果 \(s\) 在前 \(x\) 和后 \(x\) 个数之和之间,则一定可以找到一组方案满足要求
证明:类比于有 \(x\) 个点,从最小的 \(x\) 个点开始往上爬,每次最高的点开始慢慢向上爬,然后次高的点……每次权值和都只增加 \(1\),最后全部爬到最大的 \(x\) 个点上,故之间的所有 \(x\) 个数组成的和都可以取到,得证。

所以本题可以从 \(1\)\(n\) 开始一个数一个数判断是否可以凑出给定的和

  • 时间复杂度:\(O(n)\)

代码

// Problem: E. Permutation by Sum
// Contest: Codeforces - Codeforces Round #713 (Div. 3)
// URL: https://codeforces.com/contest/1512/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

int t,n;
int l,r,s,a[505];
int main()
{
    for(cin>>t;t;t--)
    {
    	cin>>n>>l>>r>>s;
    	vector<int> res;
    	int m=r-l+1;
    	for(int i=1;i<=n;i++)
    		if(s>0&&m>0&&(i+1)*(m-1)+(m-1)*(m-2)/2<=s-i&&s-i<=n*(m-1)-(m-1)*(m-2)/2)res.pb(i),s-=i,m--;
    	if(res.size()!=r-l+1)puts("-1");
    	else
    	{
    		unordered_set<int> s;
    		for(int i=l,j=0;i<=r;i++)s.insert(res[j]),a[i]=res[j++];
    		int t=1;
    		for(int i=1;i<l;i++)
    		{
    			while(s.count(t))t++;
    			a[i]=t++;
    		}
    		for(int i=r+1;i<=n;i++)
    		{
    			while(s.count(t))t++;
    			a[i]=t++;
    		}
    		for(int i=1;i<=n;i++)cout<<a[i]<<' ';
    		puts("");
    	}
    }
    return 0;
}
posted @ 2022-05-27 23:30  zyy2001  阅读(23)  评论(0编辑  收藏  举报