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 鋪設道路
瞬間想到積木大賽,原題?讀了遍,沒發現什麼問題啊?
T2 貨幣系統
思路很簡單,就是把排序後可以用它前面的數表示的數都劃掉就好了。
80%的資料好小,從資料範圍來看狀壓可以壓得下?不很會……
寫個篩也許能騙一點分?
T3 賽道修建
看到二分標誌性詞語!看到一棵樹!看到LCA!然而並不會……
看子任務:
有菊花圖,有鏈,有裸樹的直徑……55分裸暴力,良心!
8:40–8:45
處理資料夾,in/out流。
8:45–9:00
5分鐘敲完T1 + 一遍過樣例 + 一遍過並不大的大樣例。
5分鐘思考€€£出大原題的意圖。
5分鐘測試了下。
9:00-10:20
做T2。
先敲了一個 的篩,手算了資料,好像思路沒問題。
然後開始想80%的子任務……
感覺狀壓一下可以的,然後怎麼辦,怎麼辦……
過了20min後,決定放棄狀壓,感覺這部分子任務是假的。
那我就把之前的篩優化下交上去吧。
看了看暴力篩,發現複雜度夠過80%資料了……我的20min?
然後寫優化——
首先那些不需要的數可以不被篩的,這樣每次就最多隻用篩n個數了。
然後在程式里加了3個continue優化下,據說 continue / break 可以獲得玄學效率。
測大樣例,WA?發現寫出了 memset(canuse,0,sizeof(0))
大樣例pass,時間9:45。
開始造極端資料測時間,主要測了 連續的整數 / 互質的數 / 兩兩不互質的數 / 隨機數。
程式跑的極慢,檢查發現其中一個看似很有用的 continue 沒有起到一點作用,原因竟是手滑把a[i]寫成了i ……
極端資料本地卡過。也許這個篩可以水。
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%的資料環套樹。斷環為鏈卡卡常也許可以過,有點懸?
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分,過了大樣例。
開始肝環套樹。
先排了個序,害怕常數,放棄了斷環為鏈。
好像搜尋可以過。
由於環套樹的環是簡單環,所以可以從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;
}