1. 程式人生 > >AtCoder從小白到大神的進階攻略

AtCoder從小白到大神的進階攻略

前言

現在全球最大的程式設計比賽記分網站非CodeForces和AtCoder莫屬了,@ezoixx130大佬已經在去年介紹過CodeForces了(傳送門),那麼現在我們主要談一下AtCoder。

簡介

AtCoder是日本最大的演算法競技網站,正式創立於2012年6月20日,由AtCoder Inc.執行並維護,其域名為https://atcoder.jp/。提供程式設計線上比賽、過往比賽提交、線上評測等服務。

使用

首頁

1.頂部選單欄功能:

名稱 功能
Logo圖示及Home 返回首頁
Contest 比賽列表
Ranking 檢視使用者排名
English 選擇語言
個人ID 檢視個人資訊

2.左側列表:

  • Contest

Permanent Contests

此欄中列舉的是正在進行的比賽,其中的practise contest長期進行,此比賽主要目的是熟悉AtCoder的評測系統,不計分不排名。如果你對AtCoder的評測方式一無所知,可在此比賽中練習。

Upcoming Contests

可以在此檢視即將舉行的比賽並報名。

Recent Contests

最近結束的十場比賽,按照時間排序。你可以隨意開啟任意一場比賽,無需報名即可做題。

  • Ranking

榜中列舉的是活躍使用者前十名。如果長時間未參加AtCoder比賽,即使Rating未發生任何變化,賬號也會被從Rank榜中移除。

3.右側列表:

  • Information

AtCoder基本資訊、使用方式及答疑等。

  • 公告欄

通常情況下,在比賽開始的前一天,網站管理員會在此公告欄和CodeForces部落格同時釋出比賽公告以宣傳比賽。此為AtCoder Grand Contest 028位於Codeforces的宣傳介面。

比賽

1.比賽型別:
AtCoder官方比賽分為以下三種:

  • AtCoder Beginner Contest (ABC)

這是最頻繁且最簡單的入門賽,通常情況下每月至少舉行2次。2019年4月27日(含)之前,每場比賽共4題,滿分1000分且Rating超過1199的選手不計Rating值。自2019年5月19日起改版升級為6道題目,滿分2100分且Rating值超過1999的選手不計Rating值。改版之後比賽質量和參加人數均有較大突破和提升。由於入門賽題目較簡單,因此許多參賽者會選擇倒序做題。賽題按照洛谷的難度評級約為紅題~藍題,本類比賽題目具有極強的教育意義,因此建議初學者或參加普及組的選手多參加此比賽以鍛鍊程式碼熟練度。

  • AtCoder Regular Contest (ARC)

這是AtCoder的常規賽,共四道題目,滿分2100至2700不等,Rating超過2799的選手不計Rating值。特別地,本比賽一般與ABC同時進行,ABC的C、D題與本比賽前兩題相同,因此ARC賽題通常編號為C~F,ABC編號A~D。題目難度中等,賽題按照洛谷的難度評級約為黃題~紫題。按照AtCoder官網所述,此比賽原應比AGC更頻繁,但是事實上自2018年9月29日的ARC103後此比賽便再未舉行過。

  • AtCoder Grand Contest (AGC)

這是AtCoder最優秀的比賽,題目全部聘請特級選手進行原創。通常情況下賽題具有較大的思維難度。每月一般會舉行1次,6道題目共5600分。所有選手均計Rating值。

2.記分方式

比賽題目一般不設部分分,AC則得全分,否則每次失敗提交會罰時5分鐘。最終排名以得分倒序統計,得分相同時按時間升序統計。這是最近一道具有部分分的賽題。

同時每次比賽時都會根據排名得出一個表現分,表現分值與名次正相關,與個人Rating無關,但Rating的增長與否由表現分決定。

3.比賽時間

通常情況下,北京時間每週六或週日20時都會舉行比賽。相對於CodeForces來說比賽時間更加友好。

4.比賽介面

  • 頂部選單欄:
名稱 功能
Top 比賽資訊首頁
Tasks 比賽題目列表
Clarifications 提問答疑
Submit 提交程式碼
Results 比賽提交記錄及得分
Standings 比賽實時排名
Custom Test 線上IDE
Editorial 賽後題解,以AGC038的官方題解為例
Discuss CodeForces比賽討論區
  • 提交記錄

提交程式碼後可在Results>My Submissions>Detail中實時檢視每個測試點的執行結果,但不會顯示測試點內容。

在比賽結束後可檢視他人的提交記錄且程式碼公開。

  • Standings

在排名頁面可顯示所有人的做題狀態,以便控制自己做題的速度,通常情況下比較強的大佬可在25分鐘內AK ABC,45分鐘ARC,70分鐘AGC。

AtCoder無社群功能,也就是說,在沒有比賽進行時,是不可以發討論尋求幫助的,但是可以在比賽對應的CodeForces宣傳介面進行詢問,有沒有人回覆那就是另一回事了

5.比賽備用網址

AtCoder的比賽不僅在主站中舉行,在比賽特殊網址之中也同時進行,無任何區別。如果主站載入較慢或顯示出錯,那我們可以到比賽副站中參加。

比賽副站可根據比賽名稱構造,例如AGC038的比賽副站為https://agc038.contest.atcoder.jp,其主站https://atcoder.jp/contests/agc038。

Rating系統

不同的Rating等級對應著不同的ID顏色,ID會有八種正常顏色和兩種特殊顏色。與CoderForces系統不同,Atcoder初始Rating值為0。

1.正常顏色

顏色 Rating範圍
灰色 0~399
棕色 400~799
綠色 800~1199
藍色 1200~1599
淺紫色 1600~1999
黃色 2000~2399
橙色 2400~2899
紅色 2900+

2.特殊顏色

未參加任何比賽的ID會呈現黑色,身為網站管理員的賬戶為紫色。

3.Rating介面展示

個人資訊

1.My Profile

檢視個人資訊,包含全站排名、Rating變化記錄、參賽記錄等資料。

2.General Settings

可更改暱稱、繫結推特賬號和CF賬號、設定國籍、出生日期、工作地等個人資訊。特別注意,登入時使用的使用者名稱只允許更改一次,但比賽時顯示的暱稱允許修改多次。

3.Change Photo

修改個人頭像。

4.Change Password

更改密碼。

5.Manage Fav

在他人個人頁面可點選五角星進行關注操作,關注後可以在此檢視。注意手動同步本地與雲端資料。

6.Sign Out

退出登入。

語言切換

為什麼要著重說一下AtCoder網站的語言呢?

與其它網站不同,AtCoder英文和日文介面中的功能是不完全相同的,即語言的切換會導致功能的變化。以下為日文網頁,此網頁與上文中英文首頁圖片在同一時間截圖,我們可以發現,在左側正在進行中的比賽中多了兩場,在即將到來的比賽中多了一場,同時公告欄中的內容更加豐富,這些是針對日本選手特設的比賽和公告,在英文頁中無法檢視,但是在日文頁中我們同樣也可以參加。

指令碼

一個知名的網站總是少不了各種各樣的輔助指令碼,現在我們著重介紹幾個比較方便AtCoder使用的Tampermonkey指令碼。

什麼?沒有用過Tampermonkey?在瀏覽器擴充套件中心搜尋並安裝,開啟greasyfork.org搜尋你想要的網站指令碼安裝就可以使用了。

1.ac-predictor

安裝指令碼後,可以發現在介面右側多了一個側欄向左伸展的按鈕,點選即可使用其功能。

  • Estimator

可根據表現分來計算Rating值,也可根據想到達的Rating值計算所需的表現分。

  • Predictor

在比賽頁面點開側欄還會出現Predictor,可輸入本場比賽的排名算出表現分和Rating值。

  • 豐富排名介面

所有參賽者的表現分和預計Rating值都會在Standing介面顯示。

2.AtCoder Submission Status

一目瞭然地顯示AtCoder提交的答案測試資料的結果及數量。

3.AtCoderDarkTheme

為AtCoder提供夜間模式介面。非常遺憾的是,直到目前為止,還未有任何人為Atcoder寫外掛CSS樣式,因此目前夜間模式只能使用JavaScript指令碼實現。

4.AtCoderUserSearchForm

在頂欄新增使用者搜尋按鈕,查詢使用者十分方便。

例題選講

AtCoder Beginner Contest 112 C - Pyramid

題目描述

在古代的\(Snuke\)王國中,有一座用來加強\(AtCoder \ \ Inc.\)總裁\(Takahashi\)權威的金字塔。

金字塔的中心座標為\((Cx,Cy)\),其高度為\(H\)。周圍一點的座標\((X,Y)\)的高度為\(max(H-|X-Cx|-|Y-Cy|,0)\)。

探險家青木進行了一項調查,以確定這座金字塔的中心座標和高度。結果,他獲得了以下資訊:

\(Cx\),\(Cy\)為\(0\)到\(100\)(含)之間的整數,\(H\)為不小於\(1\)的整數。
另外,他獲得了\(N\)條資訊。第\(i\)條資訊是:“點\((xi,yi)\)的高度是\(hi\)。”
這足以識別中心座標和金字塔的高度。 通過上面的提示找到這些值。

輸入輸出樣例

輸入#1
4
2 3 5
2 1 5
1 2 5
3 2 5
輸出#1
2 2 6
樣例解釋

在這種情況下,中心座標和高度可以標識為\((2,2)\)和\(6\)。

輸入#2
2
0 0 100
1 1 98
輸出#2
0 0 100
樣例解釋

在這種情況下,中心座標和高度可以標識為\((0,0)\)和\(100\)。
請注意,已知\(Cx\)和\(Cy\)是\(0\)到\(100\)之間的整數。

輸入#3
3
99 1 191
100 1 192
99 0 192
輸出#3
100 0 193

資料範圍與限制

  • \(0≤N≤100\);
  • \(0≤x_i,y_i≤100\);
  • \(0≤h_i≤10^9\);
  • 輸入的座標不重複;
  • 中心座標和高度可以被唯一確定。

思路

通過觀察題目,直覺就會告訴我們直接求解並沒有那麼容易,於是我們換種思維方式,即列舉所有可能的答案判斷是否符合題意。

列舉\(Cx\)和\(Cy\),通過已知的一點高度確定\(H\),判斷所有已知條件是否均符合要求。時間複雜度\(Θ(n^2)\)。

程式碼

#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
int n,F,x[101],y[101],h[101];
inline bool check(int X,int Y,int H){
    for(register int i=1;i<=n;i++)if((((H-abs(X-x[i])-abs(Y-y[i]))<0)?0:H-abs(X-x[i])-abs(Y-y[i]))!=h[i])return false;
    return true;
}
int main() {
    scanf("%d",&n);
    for(register int i=1; i<=n; i++) {
        scanf("%d%d%d",&x[i],&y[i],&h[i]);
        if(h[i]!=0)F=i;
    }
    for(register int i=0; i<=100; i++) {
        for(register int j=0; j<=100; j++) {
            if(check(i,j,abs(i-x[F])+abs(j-y[F])+h[F])){
                cout<<i<<" "<<j<<" "<<(int)abs(i-x[F])+abs(j-y[F])+h[F]<<endl;
                return 0;
            }
        }
    }
}

AtCoder Regular Contest 103 E - Tr/ee

題目描述

你將得到一個長度為\(n\)的\(01\)字串\(s\)。任務是判斷是否存在滿足以下條件的含\(n\)個頂點的樹。

1.頂點編號為\(1,2,...,n\)。

2.邊編號為\(1,2,...,n-1\),且邊\(i\)連線點\(ui\)和點\(vi\)。

3.如果\(s\)中的第\(i\)個字元為\(1\),則可以通過從樹中刪除一條邊來獲得大小為\(i\)的連通分量。

4.如果\(s\)中的第\(i\)個字元為\(0\),則無法通過從樹中刪除任何一條邊來獲得大小為\(i\)的連線分量。

如果存在這樣一棵樹,則構造一棵這樣的樹。否則輸出\(-1\)。若資料多解,輸出任意一種即可。

輸入輸出樣例

輸入#1
1110
輸出#1
1 2
2 3
3 4
輸入#2
1010
輸出#2
1 2
1 3
1 4
輸入#3
1111
輸出#3
-1

資料範圍與限制

  • \(2≤n≤10^5\)

思路

顯而易見,當且僅當滿足以下三種情況時有解:

  • \(s_1=1\)(刪掉任意葉節點即可得到僅含\(1\)點的連通分量);

  • \(s_n=0\)(刪掉任何一條邊最大隻能獲得含\(n-1\)點的連通分量);

  • \(s_i=s_{n-i}\)(兩組連通分量互補)。

然後,我們可以通過畫圖發現,幾個菊花圖相連形成的樹正是我們想要的答案,這種樹又稱作毛毛蟲樹(Caterpillar Tree)。

設字串\(s\)中\(1\)的個數為\(k\),構造\(1\)個長度為\(k\)的陣列\(x\)滿足\(s_{x_i}=1\),那麼我們所求的毛毛蟲樹滿足以下性質。

  • 毛毛蟲身長為\(k+1\),即樹的直徑為\(k+1\);

  • 毛毛蟲身體第\(i(2≤i≤k)\)個點上長有\(x_i-x_{i-1}-1\)只腳。

程式碼

#include<iostream>
#include<cstdio>
using namespace std;
string s;
int cnt=1,root,lst;
int main(){
    cin>>s;
    if(s[0]=='0'||s[s.length()-1]=='1'){
        puts("-1");
        return 0;
    }
    for(register int i=0;i<(s.length()>>1);i++){
        if(s[i]!=s[s.length()-i-2]){
            puts("-1");
            return 0;
        }
    }
    for(register int i=0;i<s.length();i++){
        if(s[i]=='1'){
            root=cnt;
            printf("%d %d\n",root,++cnt);
            if(lst)for(register int j=1;j<i+1-lst;j++)printf("%d %d\n",root,++cnt);
            lst=i+1;
        }
    }
}

通過這兩道題我們可以大致瞭解AtCoder的賽題並不會考過於高深的演算法,而是考思維難度較大的題目。如果上文中至少有一項內容令你感興趣的話,那就趕快註冊一個AtCoder賬號,開啟你的AK之旅吧!

完結撒花,感謝大家!

如果文中有錯誤或疏漏請大家儘快指出,謝謝