CF1284B·New Year and Ascent Sequence

初見安~這裏是傳送門:Codeforces 1284B

Sol

這個題好像有很多人沒看懂題呀……解釋一下:就是給你n個數字串,現在要你從中選兩個進行前後拼接,可以自己接自己,並且兩個不同的串A和B,A-B和B-A是兩種接法。現在定義要求是串中存在某個值前面出現了一個比他小的值,求滿足要求的拼接有多少個。

樣例二的話,7種拼接爲:【用ABC給三個串標號】AA,AB,AC,BA,CA,BC,BB。

抓住兩個要點就可以了:
1.如果某個串本身就是滿足要求的,那麼它可以和所有剩下的串進行拼接,有2n-1種。
2.兩個串拼接,如果前一個串的最小值小於後面一個串的最大值,拼起來就是合法的。

對於第二個要點我們很好處理,把每個串的最大值和最小值扔到兩個數組裏面排序後累加答案就好了,線性的。但是加上第一個要點後細節就有點多了,因爲很容易加重複。假設現在剩下x個串,我們處理到了一個自身滿足條件的串,那麼貢獻爲2x-1;如果我們緊接着又遇到了一個滿足條件的串,那麼貢獻就只有2(x-1)-1了。很明顯,因爲這兩個串連接的情況被前面那個串處理過了所以要減掉。【這個細節卡了我好久。

所以我們把這些本身就滿足要求的串扔出來單獨處理,然後再單獨考慮剩下的需要看拼接結果的串。

可以看代碼理解一下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define int long long
#define maxn 300005
using namespace std;
typedef long long ll;
int read() {
	int x = 0, f = 1, ch = getchar();
	while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
	return x * f;
}

int ans = 0, l = 1, cnt;
int n, maxx[maxn], minn[maxn], tot = 0;
signed main() {
	n = read(); cnt = n;
	for(int t, x, i = 1; i <= n; i++) {
		t = read(); 
		int tmp = 9999999; bool flag = false;
		tot++; minn[tot] = tmp; maxx[tot] = 0;
		while(t--) {
			x = read();
			if(x > tmp) flag = true;//如果前面有值比當前小,這個串自己就是滿足條件的
			tmp = min(tmp, x);
			maxx[tot] = max(maxx[tot], x);//放進最大值和最小值
			minn[tot] = min(minn[tot], x);
		}
		if(flag) tot--, ans += cnt + cnt - 1, cnt--;//如果滿足條件,ans處理一下,注意cnt
	}

	sort(maxx + 1, maxx + 1 + tot);
	sort(minn + 1, minn + 1 + tot);
	for(int i = 1; i <= tot; i++) {//處理剩下的拼接的串
		while(minn[l] < maxx[i] && l <= tot) l++;
		ans += l - 1;
	}
	printf("%lld\n", ans);
	return 0;
}
 

C題的博客後面也有。

迎評:)
——End——

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章