1. 程式人生 > >NOIp 2018 遊記+題解

NOIp 2018 遊記+題解

寫在前面

這篇遊記被某文科巨佬噴為小學生日記,大家將就看下吧別較真……

在這裡插入圖片描述

關於我

HB無名小蒟蒻zar。
來自WFLS,高一,老年女選手。
在各大oj上以 渣兒 / juruoZAR 等賬號潛水

day 0

星期五——
上了三節文化課,然後翹了第四節體育課出去吃飯了,然後就在校外碰到了我們班主任,被質問為什麼逃課……
吃完飯又去班主任辦公室交材料,並把手機忘在他桌上了整整30min……(這就很尷尬了)

下午同學們都去看考場了,我沒去,但為了翹下午的數學考試溜回家了~
回家敲模板,寫了十個左右,手疼放棄,早早地睡了~~

day 1

before 8:30

早上去考場的路上迷路了,8:15才到,只有兩根簽了,被分配了一根。
到考場發現坐在省隊巨佬lyc的後面,rp++。
寫了個A+B,和旁邊的巨佬比了下掃雷初級誰過得快。結果……旁邊的巨佬掃雷炸了,並且一直沒有掃過……

密碼:飛雪連天
看到的第一眼就想明天的密碼是不是笑書神俠……

8:30 – 8:40

看題——

T1 鋪設道路
瞬間想到積木大賽,原題?讀了3+3^{+}遍,沒發現什麼問題啊?

T2 貨幣系統
思路很簡單,就是把排序後可以用它前面的數表示的數都劃掉就好了。
80%的資料好小,從資料範圍來看狀壓可以壓得下?不很會……
寫個篩也許能騙一點分?

T3 賽道修建
看到二分標誌性詞語!看到一棵樹!看到LCA!然而並不會……
看子任務:
有菊花圖,有鏈,有裸樹的直徑……55分裸暴力,良心!

8:40–8:45

處理資料夾,in/out流。

8:45–9:00

5分鐘敲完T1 + 一遍過樣例 + 一遍過並不大的大樣例。
5分鐘思考€€£出大原題的意圖。
5分鐘測試了下。

9:00-10:20

做T2。

先敲了一個n2amax\ n^2\ a_{max} 的篩,手算了5+5^+資料,好像思路沒問題。
然後開始想80%的子任務……
感覺狀壓一下可以的,然後怎麼辦,怎麼辦……
過了20min後,決定放棄狀壓,感覺這部分子任務是假的。

那我就把之前的篩優化下交上去吧。
看了看暴力篩,發現複雜度夠過80%資料了……我的20min?

然後寫優化——
首先那些不需要的數可以不被篩的,這樣每次就最多隻用篩n個數了。
然後在程式里加了3個continue優化下,據說 continue / break 可以獲得玄學效率。
測大樣例,WA?發現寫出了 memset(canuse,0,sizeof(0))

這種玄學初始化……

大樣例pass,時間9:45。
開始造極端資料測時間,主要測了 連續的整數 / 互質的數 / 兩兩不互質的數 / 隨機數。
程式跑的極慢,檢查發現其中一個看似很有用的 continue 沒有起到一點作用,原因竟是手滑把a[i]寫成了i ……

極端資料本地卡過。也許這個篩可以水90+90^+

10:20–11:20

先寫了樹的直徑,自測了下感覺是對的。
樹的直徑,過了樣例1 + 樣例2的m改為1 ,靜態檢查了2min沒毛病。
然後寫了鏈,二分 + 貪心,好像也挺簡單的。
這時剛過了20min。

然後開始思考二叉樹。
二分是肯定要的,然後加個LCA感覺可以。
思考時間10min,也許……可能是這樣的?
把二分敲了,LCA敲了,然後就不會了。

放棄。

11:20–11:55

檢查。

T1又讀了兩遍題,隨便測了下。確認是原題。
T2不想看,又把之前測過的資料測了一遍然後跳過了。
T3檢查時發現,我菊花圖的思路錯了!
當時我認為只用把邊兩兩配對就好了,然後發現 m>2*(n-1) 時有單邊存在?
罵了自己好多遍 ** (手動河蟹),然後開始寫。

寫了10min沒寫完……

11:55–12:00

強行打斷T3菊花圖的進度。
填了桌籤,刪了.in和.out檔案,檢查除錯資訊有沒有刪。
11:58時擡頭看見lyc巨佬還在敲程式碼,被感動.jpg。

after 12:00

出考場,聽見一個不認識的巨佬說他AK了……瑟瑟
遇到mzj巨佬,說T3正解樹剖,但他沒寫。
在電梯上有巨佬說T2完全揹包但他沒寫,我說我寫了個詭異的篩,他說呵呵,心情–。
在樓下聽幾個人說ylh巨佬AK了?
我告訴教練我涼了,然後看見ouuan詭異地笑著出來了,說ylhAK了,看來ylh真的AK了。
開啟QQ,看到各大群+oj上有許多AK祭,原題*3祭,心情-inf。

下雨沒帶傘淋雨跑上車,rp–。

下午寫了半個線段樹,不想寫了,頹廢。
不太想估分。

day 2

before 8:30

到得比較早,抽了籤。
周圍人都不認識,邊上有個女孩子,前面的巨佬好像有點面熟。

密碼:笑書神俠
雖然day1已經猜到這個密碼了,但是還是看錯了,看成了 小叔神仙 ,敲錯了3遍……良心監考老師用漢語寫了密碼提示。
我day1竟然猜對了密碼……rp++。

抽到的這個考場有音響,四周都是掃雷的聲音。

8:30–9:00

先寫了繁瑣的提交格式。

看題——

T1 旅行
60%的子任務是一棵樹,排個序貪心下就好。
想到九省聯考2018 day1T2我排個序貪個心水過的60分。
100%的資料環套樹。斷環為鏈n2n^2卡卡常也許可以過,有點懸?

T2 填數遊戲
看到 矩陣 + 二元組 ,又想到了九省聯考2018 day1T1的悲慘經歷(STO ouuan)。
成功被誤導想了下輪廓線dp。
n,m<=3可以手寫打表。
n,m<=8可以暴力打表。
嗯,對,就是打表。

T3 保衛王國
並沒有再去想 九省聯考2018 ……
所以我什麼都沒想到……

心態–
感覺一定能寫對的只有60+20+0=80分保底。
感覺今年像是假的一樣,難度順序T1–T6?

9:00–10:40

20min寫了T1樹的60分,過了大樣例。

開始肝環套樹。
先排了個序,害怕常數,放棄了n2n^2斷環為鏈。
好像搜尋可以過。
由於環套樹的環是簡單環,所以可以從1開始dfs一遍搜出環的起點。
環上的路徑一定是先走字典序小的一邊,再掉頭。
所以搜尋下就好了。
寫了一個小時調過了大樣例。
用了十分鐘叉掉自己。
又用了十分鐘過了huck資料。

發現沒時間了。

10:40–11:20

左邊的妹子玩紙牌,右邊的小鴿鴿玩掃雷。

花了10分鐘手算了n,m<=3。
然後寫了半個小時暴力寫不出來。
跳過。
20分祭。

11:20–11:40

左邊的妹子開始睡覺,右邊的小鴿鴿

好慌啊,心態–。
寫了n,m<=2000的dp。

11:40–11:50

推了一下T2,沒什麼用。

11:50–12:00

檢查格式。
內心自閉了,默默的思考退役記的格式怎麼寫。

after 12:00

出門聽巨佬們說day2翻車了?都太fAKe了吧……
又跟教練說我涼了。

回家吃飯,沒有帶文化課作業,滾回學校做作業。
教室門鎖了被關在了外面,rp–。

day 不想數

期中考試徹底爆炸了,不只是我,除了jason和ouuan的幾乎所有資訊組成員好像都炸了。
唯一的女孩子(除了我)ZSY轉學了,以後競賽可下了沒人陪我吃飯了,桑心。
落咕測的380,ouuan、ylh、jason分都400+,被吊打……巨佬lyc似乎也涼了。

day 不想數 +不想數days

聽說早上10點出分,課間操和一眾巨佬去機房查分,發現分數竟然是暫無!
€€£ => GGF

中午睡過錯過競賽課+數學課+物理課,rp–。

day 不想數 +不想數days+1

聽說早上8點出分,早自習還在和ouuan說要不要待會去機房查分,mjc竟然已經查到分了……
€€£竟然還會提前出分!
Day1:100+100+50=250
Day2:84+20+24=128
總分:378
排名:HB rank 14

day1T2撿了個AC,day2果然翻車,T1都寫跪了。聽說ouuan day2T1斷環為鏈AC了?

ouuan果然是HB rank1,以後他裝蒻時有證據了。
ylh HB rank5 ,Jason HB rank8,都是吊打我的巨佬啊……

同時期待lyc巨佬和沒見過的hy學弟的省選發揮~

被教練拉出去談話,信心++。

總結

感覺該拿的暴力分好多沒拿到,時間分配也有問題……
嗚嗚嗚考前寫的模板一點都沒用到,寫了一堆dfs,還是很桑心的,還是多練練暴力吧。

題解:

更新中……

day1T1:

同積木大賽——

#include<bits/stdc++.h>
using namespace std;

#define read(x) scanf("%d",&x)
#define maxn 100000

int n;
int a[maxn+5];

int main() {
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	
	int ans=0;
	for(int i=1;i<=n;i++) {
		if(a[i]>a[i-1]) ans+=a[i]-a[i-1];
	}
	
	printf("%d",ans);
	
	return 0;
}
day1T2:

暴力篩——

#include<bits/stdc++.h>
using namespace std;

#define maxn 100
#define maxa 25000
#define read(x) scanf("%d",&x)

int n;
int a[maxn+5];

bool canuse[maxa*2+5];

int s=1,ss[maxa*2+5];

int main() {
	int T;
	read(T);
	while(T--) {
		memset(canuse,0,sizeof(canuse));
		s=1;
		
		read(n);
		for(int i=1; i<=n; i++) read(a[i]);

		sort(a+1,a+n+1);
		canuse[0]=true;
		
		int ans=0;
		for(int i=1; i<=n; i++) {
			if(!canuse[a[i]]) ans++;
			else continue;
			for(int tt=1; tt<=s; tt++) {
				int j=ss[tt];
				if(!canuse[j]) continue;
				int t=(a[n]-j)/a[i];
				for(int k=1; k<=t; k++) {
					int x=j+k*a[i];
					if(canuse[x]) continue;
					canuse[x]=true;
					ss[++s]=x;
				}
			}
			
		}

		printf("%d\n",ans);
	}

	return 0;
}
day2T3:

O(n) dfs可過,考試時寫掛了鴨?
程式碼量有點大,變數名用得也不是很清晰,以至於造成手滑……

#include<bits/stdc++.h>
using namespace std;

#define maxn 5000
#define read(x) scanf("%d",&x)

int n,m;
vector<int> a[maxn+5];

vector<int> ans;

void dfs(int x,int fa) {
	ans.push_back(x);
	for(int i=0; i<a[x].size(); i++) {
		int y=a[x][i];
		if(y==fa) continue;
		dfs(y,x);
	}
	return ;
}

bool vis[maxn+5];
int rt=0,rtt=0;

void dfs1(int x,int fa) {
	vis[x]=true;
	for(int i=0; i<a[x].size(); i++) {
		int y=a[x][i];
		if(y==fa) continue;
		if(vis[y]) {
			rt=rtt=y;
			break;
		}
		dfs1(y,x);
		if(rt) break;
	}
	if(!rt) vis[x]=false;
	if(x==rt) rt=0;
	return ;
}

int x1,x2;
bool use[maxn+5];
int flg=false;
int nn=0;

void dfs2(int x,int nxt) {
	if(vis[x]&&x>nxt&&flg==1) {
		flg=2;
		return ;
	}
	if(x==nn) flg=2;
	use[x]=true;
	ans.push_back(x);
	if(x==rtt) {
		for(int i=0; i<a[x].size(); i++) {
			int y=a[x][i];
			if(use[y]) continue;
			if(vis[y]) {
				nn=y;
			}
		}
		for(int i=0; i<a[x].size(); i++) {
			int y=a[x][i];
			if(use[y]) continue;
			if(vis[y]&&2!=flg) {
				flg=1;
			}
			dfs2(y,i==a[x].size()-1?nxt:(use[a[x][i+1]]==0?a[x][i+1]:(i==a[x].size()-2?nxt:a[x][i+2])));
		}
		return ;
	}
	for(int i=0; i<a[x].size(); i++) {
		int y=a[x][i];
		if(use[y]) continue;
		else dfs2(y,i==a[x].size()-1?nxt:(use[a[x][i+1]]==0?a[x][i+1]:(i==a[x].size()-2?nxt:a[x][i+2])));
	}
	return ; 
}

int main() {
	read(n),read(m);
	for(int i=1; i<=m; i++) {
		int x,y;
		read(x),read(y);
		a[x].push_back(y);
		a[y].push_back(x);
	}
	for(int i=1; i<=n; i++) sort(a[i].begin(),a[i].end());
	if(m==n-1) {
		dfs(1,0);
		for(int i=0; i<ans.size(); i++) printf("%d ",ans[i]);
	} else {
		dfs1(1,0);
		dfs2(1,1e9);
		for(int i=0; i<ans.size(); i++) printf("%d ",ans[i]);
	}

	return 0;
}