1. 程式人生 > >NOIP模擬(10.27)T1 壽司

NOIP模擬(10.27)T1 壽司

壽司

題目背景:

10.27 NOIP模擬T1

分析:暴力

老子有句喵喵喵真的非常想講······

覺得今天T1最難的一定不是隻有我,T1程式碼最長的也一定不是隻有我,總之這個真的叫T1嗎,不過給我留了50分我還真是謝謝你了······

直接講題吧,考慮如果我們先不考慮成環的問題,那麼很顯然的我們需要將B給移到兩邊,或者R移到兩邊,我們這裡直接說R吧,顯然,這樣做的答案,應該是,每一個被移到左邊去的R左邊原來的B的個數,每一個被移到右邊去的R右邊原來的B的個數,那麼很顯然的,我們最好的方式是將,第(B的總個數 + 1) / 2B(以下將第(B的總個數 + 1) / 2B的位置簡稱為

pos)左邊的R全部移到左邊,右邊的R移到右邊,現在我們就有了一種很暴力的O(n2)做法了,就是將這個串的n個迴圈同構串都這麼找到中間的B然後統計一下答案,取最小就好了,顯然我們看看資料範圍,還是停止了這種naïve的想法······考慮如何在迴圈同構的過程中維護第(B的總個數 + 1) / 2B所在的位置和當前的答案,考慮每一次更改我們都將當前字串的第一個字元移到最後去,假如這一個字元為B,那麼如果我們原來的pos不移動,那麼就是原來pos左邊的所有R的貢獻都會減少1pos右邊的都會加上1,這樣就維護了答案,再考慮如何移動pos,顯然,我們只需要往後面找到下一個B所在的位置就是新的pos
了,那麼在移動過程中就有很多的R從原來的pos右邊,變成了pos左邊,那麼我們減去它右邊的B的數量,加上它左邊的B的數量就可以了。這些操作都可以通過維護RB的字首和來比較方便的完成。複雜度O(Tn)

Source

/*
	created by scarlyw
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <cctype>
#include <queue>
#include <vector>
#include <ctime>

const int MAXN = 2000000 + 10;
const long long INF = 1000000000000000000;
int t, len, n;
int lb[MAXN], lr[MAXN], rb[MAXN], rr[MAXN];
char s[MAXN];

int main() {
	std::ios::sync_with_stdio(NULL);
	std::cin.tie(NULL), std::cout.tie(NULL);
	std::cin >> t;
	while (t--) {
		std::cin >> (s + 1), len = strlen(s + 1);
		long long fans1 = INF;
		for (int i = 1; i <= len; ++i) s[i + len] = s[i];
		n = len, len *= 2;
		for (int i = 1; i <= len; ++i) {
			lb[i] = lb[i - 1], lr[i] = lr[i - 1];
			if (s[i] == 'B') lb[i]++;
			else lr[i]++;
		}
		for (int i = len; i >= 1; --i) {
			rb[i] = rb[i + 1], rr[i] = rr[i + 1];
			if (s[i] == 'B') rb[i]++;
			else rr[i]++;
		}
		long long ans1 = 0;
		int pos = (lb[n] + 1) / 2, p = -1;
		for (int i = 1; i <= n; ++i) {
			if (lb[i] == pos) {
				p = i; 
				for (int j = n; j >= i; --j)
					if (s[j] == 'R') ans1 += (long long)(rb[j] - rb[n + 1]);
				break ;
			}
			if (s[i] == 'R') ans1 += (long long)lb[i];
		}
		int head = 1, tail = n;
		fans1 = ans1;
		while (head <= n) {
			if (s[head] == 'B') {
				ans1 -= lr[p] - lr[head - 1];
				ans1 += rr[p] - rr[++tail], ++head;
				while (s[++p] != 'B') {
					ans1 += (long long)(lb[p] - lb[head - 1]);
					ans1 -= (long long)(rb[p] - rb[tail + 1]);
				}
			} else head++, tail++;
			fans1 = std::min(fans1, ans1);
		}
		std::cout << fans1 << '\n';
	}
	return 0;
}