首页 > 其他分享 >AGC-059解题报告

AGC-059解题报告

时间:2023-03-01 16:22:41浏览次数:59  
标签:now string int 元素 AGC ++ 解题 059 include

比赛传送门

A. My Last ABC Problem

题意:有一个只含 ABC 字符串 \(s\),每次询问一段区间 \([l,r]\),问至少需要多少次操作能将这段区间变得完全相同。每次操作可以选一段区间 \([a,b]\) 和一个 \({A,B,C}\) 的排列,将这段区间内按照排列描述的方式进行替换。

很容易想到考虑连续段,以下描述中一个元素均表示一个连续段。可以发现,每次操作的元素个数要么 \(-1\) 要么 \(-2\),所以考虑什么时候可以 \(-2\)。我们发现,当某个元素的左右两边相同时,可以直接将这个元素改为和左右两边相同,此时可以 \(-2\);当与左右两边不同时,可以发现,若段数 \(\ge 5\),一定可以 \(-2\),方式为:任选连续五个元素,由于任意元素的左右两边不同,一定形如 ABCAB,此时将中间的三个元素 BCA->ABC 即可满足要求。还发现一个性质,即 \(-2\) 的时候一定不会改变两端。所以考虑反复进行 \(-2\),直到元素个数为 \(3\) 或 \(4\)。此时,当元素个数为 \(4\) 时答案一定为 \(2\);元素个数为 \(3\) 时答案取决于两端是否相等。可以统一情况如下:

By cxm1024

#include<bits/stdc++.h>
using namespace std;
int f[100010];
signed main() {
	int n,q;
	string s;
	cin>>n>>q>>s;
	for(int i=0;i<s.size();i++)
		if(i>0) f[i]=f[i-1]+(s[i]!=s[i-1]);
	while(q--) {
		int l,r;
		cin>>l>>r;
		l--,r--;
		if(s[l]==s[r]) cout<<(f[r]-f[l]+1)/2<<endl;
		else cout<<(f[r]-f[l])/2+1<<endl;
	}
	return 0;
}

错解:

By daisybunny

#include<bits/stdc++.h>
using namespace std;
int n;
string s;
int q;
vector<int> v;
int sum[3][100005];
int main()
{
	cin>>n>>q>>s;
	v.push_back(0);
	for(int t=1;t<n;t++)
		if(s[t]!=s[t-1])
			v.push_back(t);
	for(int t=0;t<v.size();t++)
	{
		sum[s[v[t]]-'A'][v[t]+1]++;
	}
	for(int t=1;t<=n;t++)
		for(int i=0;i<3;i++)
			sum[i][t]+=sum[i][t-1];/*
	for(int t=0;t<3;t++)
	{
		for(int i=1;i<=n;i++)
			cout<<sum[t][i]<<" ";
		cout<<endl;
	}*/
	while(q--)
	{
		int l,r;
		cin>>l>>r;
		int a=sum[0][r]-sum[0][l-1],b=sum[1][r]-sum[1][l-1],c=sum[2][r]-sum[2][l-1];
		cout<<a+b+c-max(a,max(b,c))<<endl;
	}
	return 0;
}

一组 hack 数据:ABCABCA。这份代码直接选两种较少的颜色累加,但实际上每次操作可以 \(-2\),所以必然有 \(/2\) 的操作。

By startcpp

//O(NQ) ....
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cmath>
#include <tuple>
#include <random>
#include <cassert>
#include <unordered_map>
#define rep(i, n) for(i = 0; i < n; i++)
#define int long long
using namespace std;

mt19937 mt(2521);

int naive(string s) {
	queue<string> que;
	unordered_map<string, int> dp;
	map<string, string> prevS;
	vector<vector<int>> perms = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2}, {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};

	que.push(s);
	dp[s] = 0;
	int ret = -1;
	string ret_s;
	while (!que.empty()) {
		string now = que.front(); que.pop();
		int n = now.length();

		bool check = true;
		for (int i = 0; i < n - 1; i++) {
			if (now[i] != now[i + 1]) { check = false; break; }
		}
		if (check) { ret = dp[now]; ret_s = now; break; }

		for (int i = 0; i < 6; i++) {
			for (int l = 0; l < n; l++) {
				string t;
				for (int r = l; r < n; r++) {
					int x = perms[i][now[r] - 'A'];
					t += (char)(x + 'A');
					string nxt;
					for (int k = 0; k < l; k++) nxt += now[k];
					nxt += t;
					for (int k = r + 1; k < n; k++) nxt += now[k];
					if (dp.find(nxt) == dp.end()) {
						dp[nxt] = dp[now] + 1;
						prevS[nxt] = now;
						que.push(nxt);
					}
				}
			}
		}
	}

	/*for (int i = 0; i < ret; i++) {
		cout << ret_s << endl;
		ret_s = prevS[ret_s];
	}
	cout << ret_s << endl;*/
	return ret;
}

int greedy(string s) {
	int i;
	string ss;
	rep(i, s.length()) {
		if (i > 0 && s[i - 1] == s[i]) continue;
		ss += s[i];
	}
	//cout << "ss = " << ss << endl;

	int ret = ss.length();
	int n = ss.length();
	typedef pair<int, char> P;
	for (char c = 'A'; c <= 'C'; c++) {
		vector<P> vec;
		int len = 0; char first_char = '-';

		//cout << "c = " << c << endl;
		rep(i, n) {
			if (ss[i] == c) {
				if (len > 0) vec.push_back(P(len, first_char));
				len = 0;
				continue;
			}
			if (len == 0) first_char = ss[i];
			len++;
		}
		if (len > 0) vec.push_back(P(len, first_char));

		int cst = 0;

		rep(i, vec.size()) {
			cst += vec[i].first / 2 + 1;
		}

		int cnt = 0;
		for (int i = 0; i < vec.size(); i++) {
			if (vec[i].first % 2 == 0) cnt++;
		}
		cst -= cnt / 2;
		//cout << "cst = " << cst << endl;
		ret = min(ret, cst);
	}
	return ret;
}

void solve_input() {
	int n, Q;
	cin >> n >> Q;
	string s;
	cin >> s;
	for (int i = 0; i < Q; i++) {
		int l, r;
		cin >> l >> r; l--; r--;

		string t;
		for (int j = l; j <= r; j++) t += s[j];
		cout << greedy(t) << endl;
	}
}

signed main() {
	solve_input();
	return 0;

	//naive("ABCCACABC");
	//return 0;

	/*int n = 10, i;
	int T = 2000;

	for (int t = 0; t < T; t++) {
		cout << "t = " << t << endl;
		string s;
		rep(i, n) {
			s += (char)(mt() % 3 + 'A');
		}
		int res1 = naive(s);
		int res2 = greedy(s);
		if (res1 != res2) {
			cout << s << " " << res1 << " " << res2 << endl;
			break;
		}
	}

	return 0;*/
}

这份代码每次询问都 \(O(n)\) 计算,总复杂度达到 \(O(qn)\),必然会超时。正解一定需要预处理再回答询问。

如果要设计测试数据,需要充分考虑边界情况,如只有一个元素、只有一种元素、每个元素段的长度均为 \(1\)、只有两种元素等等。除了边界情况,还要通过随机来保证正常数据的强度。既要有两端相同的询问,也要有两端不同的询问。段数少的情况可以枚举所有情况各处一组询问。例如:

32 17
ABCABCABCAAAAAAABABABCACBABCBACA
1 1
2 2
3 3
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
10 15
16 21
22 32
24 30
25 31
1 32

标签:now,string,int,元素,AGC,++,解题,059,include
From: https://www.cnblogs.com/cxm1024/p/17168398.html

相关文章

  • CFR-826-Div-3解题报告
    F.Multi-ColoredSegments题意:数轴上有\(n\)个线段,每个区间有一个颜色\(c\),对于每个线段,求与它颜色不同的线段中与它的最短距离。距离定义为两个线段中的点集最近的......
  • CFR-832-Div-2解题报告
    B.BANBAN题意:给你一个\(n\),生成一个字符串为BAN重复\(n\)遍。每次操作可以选择两个位置进行交换,问至少多少次交换后可以使该串不存在BAN的子序列。输出方案。......
  • CFR-755-Div-2解题报告
    比赛传送门赛时AC三道,补题做出一道。A.MathematicalAddition{%noteinfono-iconProblem%}给你两个正整数\(u,v\),求一对合法的\(x,y\)使得\(\frac{x}{u}+\fra......
  • CFR-844-Div-1-2解题报告
    比赛传送门A.ParallelProjection题意:有一个\(w\timesd\timesh\)的长方体,顶面和底面有两个点,只能走直线且不能穿过长方体,求最短距离。显然曼哈顿距离必须要走。......
  • CFR-745-Div-2解题报告
    没打比赛,赛后做出3道。这场比赛题目质量很高,非常巧妙。A.CQXYMCountPermutations\(Problem\)求有多少\(2n\)的排列满足存在超过\(n\)个\(i\)使得\(p_i<p_{i+......
  • CFR-746-Div-2解题报告
    VP做出来一道,补题又做出来3道。A.GamerHemose\(Problem\)你有\(n\)个武器,要打一个体力为\(H\)的敌人,第\(i\)个武器可以对敌人造成\(a_i\)的伤害,每把武器不能......
  • CFR-109解题报告
    A.Hometask题意:一个字符串,给定\(k\)个限制字符对\((a_i,b_i)\),要求从原串中删除尽可能少的字符,使得不存在一个相邻的限制字符对。保证\(a_i\neb_i\),且每个字符最多......
  • CFR-744-Div-3解题报告
    赛时AC2道题,掉大分(哭)A.Casimir'sStringSolitaire题目传送门\(Problem\)给你一个仅含A,B,C的字符串,每次可以删掉一个A和一个B,或一个B和一个C,位置、顺序不......
  • CFR-840-Div-2解题报告
    比赛传送门C.AnotherArrayProblem题意:给你一个数组\(a\),每次可以选两个位置\(i,j(i<j)\),将\([i,j]\)内的所有数替换为\(|a_i-a_j|\)。问最终数组的和最大为多少......
  • CFR-843-Div-2解题报告
    比赛传送门C.InterestingSequence题意:给你\(n,x\),求最小的\(m\gen\),使\(n\&(n+1)\&(n+2)\&\cdots\&m=x\),或判断无解。首先每一位独立,分别考虑。与运算每一位都......