1. 程式人生 > 實用技巧 >Codeforces Round #683 (Div. 2, by Meet IT) 題解&總結

Codeforces Round #683 (Div. 2, by Meet IT) 題解&總結

值得紀念。

但以後不會再有了QAQ

A

其它的增高相當於自己降低。所以按順序輸出\(1\)\(n\)即可。

(由於一開始看反了導致掛了一次……)

B

兩點間隨意找一條路徑操作,路徑中間的點沒有影響,只會影響端點。

全域性找任意對數將其符號取反。貪心即可。

C

先從大到小排序,能選就選。由於要求的下界是上界的一半,從大往小選,不存在少選一個大的,多選幾個小的才能滿足的情況。

(似乎不排序也能做)

D

樸素DP。直接設\(f_{i,j}\),也就是普通的LCS問題改點細節而已。

E

D到E花了1.5h,E到F1花了不到0.5h。我在幹嘛……

https://www.cnblogs.com/jz-597/p/13986661.html

F

顯然全域性眾數也是最優區間的眾數之一(否則考慮最優區間擴張的過程,必定存在一次區域性眾數和全域性眾數的出現次數相等)。

找出全域性眾數,分別列舉每一個數,變成如下問題:全域性眾數出現的位置為\(+1\),這個數出現的位置為\(-1\),其它位置為\(0\),求最長的和為\(0\)的區間。

第一檔部分分直接開個桶來維護。時間\(O(100n)\)。貼程式碼:

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200005
int n,m;
int a[N];
int s[N][101];
int p[N];
int buc[N*2];
void upd(int &a,int b){
	if (a==-1) a=b;
}
int main(){
//	freopen("in.txt","r",stdin);
	scanf("%d",&n);
	for (int i=1;i<=n;++i){
		scanf("%d",&a[i]);
		memcpy(s[i],s[i-1],sizeof s[i]);
		s[i][a[i]]++;
	}
	int id=1,mx=s[n][1];
	for (int i=2;i<=100;++i)
		if (s[n][i]>mx)
			mx=s[n][i],id=i;
		else if (s[n][i]==mx)
			id=-1;
	if (id==-1){
		printf("%d\n",n);
		return 0;
	}
	p[0]=0;
	for (int i=1;i<=n;++i)
		if (a[i]==id)
			p[++m]=i;
	p[++m]=n+1;
	memcpy(s[n+1],s[n],sizeof s[n]);
	int ans=0;
	for (int i=1;i<=100;++i){
		if (i==id)
			continue;
		memset(buc,255,sizeof buc);
		for (int j=0;j<=m;++j){
//			if (j==3)
//				j=3;
//			printf("query(%d)\n",s[p[j]][i]-j);
			if (buc[s[p[j]][i]-j +N]!=-1)
				ans=max(ans,p[j]-buc[s[p[j]][i]-j +N]-1);
//			printf("upd(%d,%d)\n",s[p[j]][i]-j-1,p[j]);
			upd(buc[s[p[j]][i]-j-1 +N],p[j]);
		}
	}
	printf("%d\n",ans);
	return 0;
}

對於第二檔,題解做法:如果這個數的出現次數\(|V|>\sqrt n\),那麼用上述方法\(O(n)\)做;否則,對於這個數的每個出現位置\(V_i\),提取出左右離它最近的全域性眾數,一共要做\(O(|V|)\)個位置,每個位置要麼是一個\(-1\)或一段\(+1\)。可以直接\(O(|V|^2)\)。總時間\(O(n\sqrt n)\)

其實也可以做到\(O(n\lg n)\)。用線段樹維護區間的字首最大值和最小值。當需要找一個值的的第一次出現位置的時候,由於每次只會\(+1\)\(-1\),是連續的,如果這個值在最小值最大值之間,就一定存在。那麼線上段樹上二分即可。

都沒寫。


感覺這次發揮比較好。

原因大概有:

  1. 這次咖啡選擇在晚餐後喝,比賽期間精神飽滿,腎上腺素激增,上廁所時能感受到心跳,打題時感覺到右臂的動脈在動。(我不是在吹)。
  2. 這次題目比較適合我發揮,不像上次div2那樣全場構造。
  3. 2:30的寫題時間,第一次div2切了超過4題。
  4. 秒切了不知道為什麼沒什麼人寫的F1。

當然了這次也存在一些敗筆。在想題的時候(尤其是E題),繞了很長的彎子,中間想了個可能不靠譜的陰間做法,交了一遍自然掛了。感覺應該要更嚴謹一些,那種做法應該被ban掉的。

div1我來啦!