webpack配置
Avoid Trygub
題意:
給你一個字串,重排它讓它不出現$"trygub"$子序列。$n \leq 100$。
題解:
對這個字串的字元直接排序即可。
Balls of Steel
題意:
給你$n$個點和$k$,每次選擇一個點,使得和它的曼哈頓距離小於$k$的點都被它吸引(到它的位置),問多少次操作能使所有點都在一個位置,不能則輸出$-1$。$n \leq 100$。
題解:
顯然要麼一次,要麼不能。暴力判斷一下點之間的距離就行。
Errich-Tac-Toe (Easy Version)
題意:
一個$n * n$的棋盤上有$'.'$和$'X'$,三個$'X'$橫著或豎著連續,則算贏局,否則算平局,給出一個局面,現在你需要把最多$\lfloor \frac{k}{3} \rfloor$的位置($k$為$'X'$的個數)改成$'O'$,讓它變成平局,輸出方案。
題解:
想了很多方法$QAQ$,但是完全沒注意到染色的笨蛋。考慮染色,其實我們可以發現,連著的三個$'X'$座標($x_i,y_i$)的和$x_i+y_i$構成模$3$的完全剩餘系,按照這個染色。這樣子我們只需要算出每種顏色的$'X'$有多少,把最少$'X'$的顏色的$'X'$全部染成$'O'$即可。
Errich-Tac-Toe (Hard Version)
題意:
一個$n * n$的棋盤上有$'.'$和$'X'$和$‘O’$,三個$'X'$或者三個$'O'$橫著或豎著連續,則算贏局,否則算平局,給出一個局面,現在你需要把最多$\lfloor \frac{k}{3} \rfloor$的位置($k$為$'X'$的個數)改成$'O'$,反之亦然,讓它變成平局,輸出方案。
題解:
同上,我們保證一種顏色沒有$'X'$,另一種顏色沒有$'O'$即可。
總結:
碰到這種連著的題,可以考慮模$k$染色的做法。
Rating Compression
題意:
給出一個序列,問對於$1 \leq i \leq n$,長度為$i$構成的滑動視窗的最小值形成的長度$n-i+1$的序列是不是一個排列。輸出一個長度是$n$的字串,第$i$位$[0/1]$表示長度為$i$的情況。
題解:
考慮一個數向左向右延伸多長,這個區間內還是以它為最小值,若視窗長度小於這個區間,顯然生成的序列就不是排列。考慮滑動視窗長度是$i$排列的性質:$1$到$n-i+1$都需要出現在排列中,排列長度是$1$到$n-i+1$。則如果$n-i+1$不出現在原序列,這個排列必不存在。因為考慮到$1$一定是最小的,則延伸長度是$n$的區間一定會是$1$,記錄$1$,考慮$2$,如果延伸長度不是$n-1$,則說明$1$不在端點,則長度是$n-1$的滑動視窗必然非法。否則記錄$2$。同樣的考慮$3$,並假設長度$n-1$的滑動視窗合法,顯然$1$和$2$要麼分別在兩端點,要麼連著,且$1$咋在端點,則$2$的延伸長度是$n-1$。記錄$3$。即$i$合法時,必須有$1~i$的記錄,此時滑動視窗的長度是$n-i+1$。考慮重複的情況:$1 3 2 1$,算出長度是$2$時的序列:$1 2 1$。按照上面的過程,滑窗長度是$3$時,沒有記錄$2$,但是記錄了兩個1,然後在滑窗長度是$2$是,記錄了$2$,此時也是滿足3個的。但是顯然這個生成序列不滿足。此時$set$去重即可。
AC程式碼:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 3e5 + 5; 4 int l[N], r[N]; 5 int s[N], a[N], cnt[N]; 6 bool vis[N]; 7 char str[N]; 8 vector<int>v[N]; 9 set<int>ss; 10 void solve() 11 { 12 int n; 13 scanf("%d", &n); 14 for (int i = 1; i <= n; ++i) 15 { 16 vis[i] = 0; 17 str[i] = '0'; 18 v[i].clear(); 19 cnt[i] = 0; 20 } 21 ss.clear(); 22 for (int i = 1; i <= n; ++i) 23 scanf("%d", &a[i]), vis[a[i]] = 1; 24 int top = 0; 25 for (int i = 1; i <= n; ++i) 26 { 27 while (top && a[i] < a[s[top - 1]]) 28 r[s[--top]] = i - 1; 29 s[top++] = i; 30 } 31 while (top) 32 r[s[--top]] = n; 33 for (int i = n; i; --i) 34 { 35 while (top && a[i] < a[s[top - 1]]) 36 l[s[--top]] = i + 1; 37 s[top++] = i; 38 } 39 while (top) 40 l[s[--top]] = 1; 41 for (int i = 1; i <= n; ++i) 42 v[r[i] - l[i] + 1].push_back(a[i]); 43 for (int i = n; i; --i) 44 { 45 if (!vis[n - i + 1]) 46 break; 47 for (auto num : v[i]) 48 ss.insert(num); 49 if (ss.size() == n - i + 1) 50 str[i] = '1'; 51 } 52 for (int i = 1; i <= n + 1; ++i) 53 printf("%c", i <= n ? str[i] : '\n'); 54 } 55 int main() 56 { 57 int t; 58 scanf("%d", &t); 59 while (t--) 60 solve(); 61 return 0; 62 }View Code