Codeforces Round #575 (Div. 3) D1,D2

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_43298454/article/details/97255924

题目链接

题意:
一个无限长的b字符串为"RGBRGB…", 现在给你一个字符串a,你可以对字符串的任意一个字符进行修改,问最少修改次数使a,b的最长公共字串长度为k。

题解:
在D1中字符串a长度最长仅为2000,因此可以遍历修改后满足a,b的最长公共字串长度为k的所有情况,维护最小次数sum即可。时间复杂度为O(nk).
PS:由于字符串a仅由’R’,‘G’,'B’构成,因此当k=1时sum = 0。


 //
//Write by Yuan Xilan on 2019...
//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
const int inf = 0x3f3f3f3f;
const int maxn = 1e+5;
char s[2020];
char s1[] = {'R','G','B'};
 
int main(int argc, char * argv[]) 
{
    std::ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while(t--){
        int n,k;
        cin >> n >> k;
        cin >> s;
        bool flag = true;
        if(k == 1){
            for(int i=0; i<n; ++i){
                if(s[i] == 'R' || s[i] == 'G' || s[i] == 'B') cout << 0 << endl;
                flag = false;
                break;
            }
            if(flag){
                cout << 1 << endl;
            }
            continue;
        }
        int minn = inf;
        for(int i=0; i+k<=n; ++i){
        	char p = s[i];
        	for(int q = 0; q < 3; ++q){
        		int sum = 0;
        		s[i] = s1[q];
        		if(p != s1[q]) sum += 1;
	            if(s[i] == 'B'){
	                for(int j=i+1; j<=i+k-1; ++j){
	                    if((j - i - 1) % 3 == 0){
	                        if(s[j] != 'R'){
	                            sum += 1;
	                        }
	                }
	                    else if((j - i - 1) % 3 == 1){
	                        if(s[j] != 'G') sum += 1;
	                    }
	                    else if((j - i - 1) % 3 == 2) if(s[j] != 'B') sum += 1;
	                }
	                //cout << sum << endl;
	            }
	            else if(s[i] == 'R'){
	                for(int j=i+1; j<=i+k-1; ++j){
	                    if((j - i - 1) % 3 == 0){
	                        if(s[j] != 'G'){
	                            sum += 1;
	                        }
	                }
	                    else if((j - i - 1) % 3 == 1){
	                        if(s[j] != 'B') sum += 1;
	                    }
	                    else if((j - i - 1) % 3 == 2) if(s[j] != 'R') sum += 1;
	                }
	            }
	            else if(s[i] == 'G'){
	                for(int j=i+1; j<=i+k-1; ++j){
	                    if((j - i - 1) % 3 == 0){
	                        if(s[j] != 'B'){
	                            sum += 1;
	                        }
	                }
	                    else if((j - i - 1) % 3 == 1){
	                        if(s[j] != 'R') sum += 1;
	                    }
	                    else if((j - i - 1) % 3 == 2) if(s[j] != 'G') sum += 1;
	                }
	            }
	            minn = min(minn,sum);
	        }
        }
        cout << minn << endl;
    }
    return 0;
}

当n,k均为2e5时,可以改用以下思路:
pre[i]数组记录字符串a从下标从1到i逐个修改,使a,b的最长公共字串长度为i的次数,可用前缀和记录,时间复杂度为O(n)。

//
//Write by Yuan Xilan on 2019...
//
#include <bits/stdc++.h>
using namespace std;

const char str[] = "RGB";
const int maxn = 2e5+5;
const int inf = 0x3f3f3f3f;
char s[maxn];
int pre[maxn];

int main(){
	int t,n,k;
	scanf("%d",&t);
	int minn;
	while(t--){
		scanf("%d%d",&n,&k);
		scanf("%s",s+1);
		minn = inf;
		for(int i=0; i<3; ++i){
			for(int j=1; j<=n; ++j){
				if(s[j] != str[(i+j)%3]) pre[j] = 1;
				else pre[j] = 0;
			}
			for(int j=1; j<=n; ++j){
				pre[j] += pre[j-1]; 
			}
			for(int j=k; j<=n; ++j){
				minn = min(minn,pre[j] - pre[j-k]);
			}
		}
		printf("%d\n",minn);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_43298454/article/details/97255924