CF第633場 (Div. 2)

CF第633場 (Div. 2)

今天開始也開始寫cf題解了,致力於分析巧解和題目的思維。
本次戰績:慘不忍睹,一直卡D,看來必須要進行數據結構了,說的也是,dfs和bfs都不會寫是真的丟人。
在這裏插入圖片描述

A題Filling Diamonds

可能很多人是輸入n輸出n
簡單提一下爲什麼是n種,因爲每一種的區別在豎着的位於哪一塊。
比如n=4的時候:
對於第一個
在這裏插入圖片描述
在這裏插入圖片描述
你可能已經發現了,所以是這個樣子:
在這裏插入圖片描述

B題Sorted Adjacent Differences

題意就是排完序後是數組的前後差值越來越大,於是可以這個樣子
在這裏插入圖片描述
怎麼確定對呢?
對於一個最大值,與它差值最大是最小值
然後一旦沒了最大值,次大值就與最小值相差最大了
(我居然邊敲邊懷疑,真是一打比賽腦子就不行)
然後就直接使用algorithm裏面的sort,找個左下標和右下標往中間靠

#include<iostream>
#include<algorithm>
using namespace std;
int q[100007];
int an[100007];
int main(){
	int t;
	cin >> t;
	while (t--){
		int n;
		scanf("%d", &n);
		int l = 0, r = n - 1;
		for (int i = 0; i < n; i++)
			scanf("%d", &q[i]);
		sort(q, q + n);
		for (int i = n-1; i >=0; i--){
			if (i & 1)
				an[i] = q[l++];
			else
				an[i] = q[r--];
		}
		for (int i = 0; i < n; i++)
			printf("%d%c", an[i],i==n-1?'\n':' ');
	}
	return 0;
}

C題Powered Addition

其實就是給你一個數組,讓你把這個數組變成一個非嚴格遞增數組,比如1,1,2什麼的。
然後第一次可以給數組中一些元素加1,第二次可以加2,第三次可以加4,第四次可以加8…第n次可以加2^(n-1)。
當時一想覺得非常麻煩,如果先變後邊,到時候前邊一變就比會後大了,後邊還得變什麼balabala什麼的,後來我突然一拍腦門。
不對啊,這不是二進制麼?二進制可以組成任何數
然後就發現,當加的值最少時。一定會出現這種情況:
在這裏插入圖片描述
很顯然了,就是所有數都要補到跟左邊已有的最大,那麼只要統計出所有max(左邊最大值-當前值)就可以了。

		int n;
		scanf("%d", &n);
		for (int i = 0; i < n; i++)
			scanf("%d", &q[i]);
		int an = 0;
		int ans = -1e9;
		for (int i = 0; i < n; i++){
			ans = max(q[i], ans);
			if (q[i] < ans)
				an = max(an, ans - q[i]);
		}

當然這算出來的是必須準備的差值,再二進制稍稍處理一下就可以了。

int s(int x){
	int in = 0;
	while (x){
		in++;
		x /= 2;
	}
	return in;
}

D題Edge Weight Assignment

關於大致的題解官方寫的更好,最小值的處理我有這樣的思想。
從度最高的節點進行BFS沒錯,就是廣搜,遇到葉子結點統計深度,然後計算奇偶。
這樣所有節點只需便利一次即可判斷。
關於廣搜的統計深度,我使用的是用-1作爲層數結束標記。
於是乎:

bool ff[100007];//用於檢測這個點有沒有被訪問過
void bfs(int x,int &j,int &o){
	queue<int> qu;//隊列
	qu.push(x);//把度最高的點壓進去
	ff[x] = 1;//這個點被訪問過了
	int an = 1;//就是一個判斷奇數偶數的,我也不知道一開始奇數還是偶數,但是如果同時出現奇偶就不是1
	qu.push(-1);//一層的標記,如果遇到-1就會取反
	while (qu.size()!=1){
		int top = qu.front();//取隊頭
		qu.pop();//取完立馬丟掉
		if (top != -1){//當不是標記時,進行常規操作
			for (int i = 0; i < q[top].size(); i++)
				if (q[q[top][i]].size() == 1)//是葉子節點
					if (an) j++;
					else o++;
				else if (!ff[q[top][i]])//壓入該點,並標記訪問(前提沒有被訪問過)
					qu.push(q[top][i]),ff[q[top][i]] = 1;
		}
		if (qu.front() == -1){//遍歷一層,進行奇偶取反,並尾部再次壓入-1標記層數
			qu.push(-1);
			an ^= 1;
			qu.pop();
		}
	}
}

代碼寫的確實很亂,但是我還是加了詳細的註解。
不要爲我爲什麼不寫DFS,我發現我不會QWQ。(寫了1個半小時的DFS還是錯的)

E題(還不會)

目前還不會,但確實發現了是這樣的:
1 2 3
4 8 12
5 10 15
6 11 13
7 9 14

本次教訓:人至少得會DFS,至少不能不會寫樹的遍歷

數據結構必須得學 QWQ

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