A. 語言
題目描述
在一個語言中,有 \(26\) 種單詞,每個單詞用一個小寫英文字母表示。每種單詞可能有多種詞性,詞性有名詞(\(N\))、動詞(\(V\))、形容詞(\(A\))。我們定義一個名詞短句(\(NP\))為一個名詞(\(N\))或一個形容詞加名詞短句(\(A+NP\))或兩個名詞短句(\(NP_1+NP_2\)),一個句子(\(S\))為一個名詞短句加動詞加名詞短句(\(NP_1+V+NP_2\))。
現在給定一些單詞,請你判斷它有沒有可能是一個句子。
思路
很明顯一段子串是名詞短句當且僅當其中只包含 \(N,P\) 且最後一個單詞為 \(N\)。所以我們列舉動詞在哪裡,並預處理前字尾是否為名詞短句即可。
時空複雜度均為 \(O(N)\)。
程式碼
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100001;
int t, n, a[26];
bool ok[MAXN];
string s;
void Solve() {
for(int i = 0; i < 26; ++i) {
cin >> a[i];
}
cin >> s;
n = s.size(), s = ' ' + s;
ok[n] = (a[s[n] - 'a'] == 2 || a[s[n] - 'a'] == 3 || a[s[n] - 'a'] == 6 || a[s[n] - 'a'] == 7);
for(int i = n - 1; i >= 1; --i) {
ok[i] = (ok[i + 1] & (a[s[i] - 'a'] == 1 || a[s[i] - 'a'] == 2 || a[s[i] - 'a'] == 3 || a[s[i] - 'a'] == 5 || a[s[i] - 'a'] == 6 || a[s[i] - 'a'] == 7));
}
bool op = (a[s[1] - 'a'] == 1 || a[s[1] - 'a'] == 2 || a[s[1] - 'a'] == 3 || a[s[1] - 'a'] == 5 || a[s[1] - 'a'] == 6 || a[s[1] - 'a'] == 7);
for(int i = 2; i < n; ++i) {
if((a[s[i] - 'a'] == 4 || a[s[i] - 'a'] == 5 || a[s[i] - 'a'] == 6 || a[s[i] - 'a'] == 7) && op && (a[s[i - 1] - 'a'] == 2 || a[s[i - 1] - 'a'] == 3 || a[s[i - 1] - 'a'] == 6 || a[s[i - 1] - 'a'] == 7) && ok[i + 1]) {
cout << "Yes\n";
return;
}
op &= (ok[i + 1] & (a[s[i] - 'a'] == 1 || a[s[i] - 'a'] == 2 || a[s[i] - 'a'] == 3 || a[s[i] - 'a'] == 5 || a[s[i] - 'a'] == 6 || a[s[i] - 'a'] == 7));
}
cout << "No\n";
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
for(cin >> t; t--; Solve()) {
}
return 0;
}
B. 色球
題目描述
有 \(N\) 個棧,和 \(N\) 種顏色的球。給定 \(M\) 次操作。
- 往第 \(z\) 個棧壓入 \(x\) 個顏色為 \(y\) 的球。
- 彈出第 \(z\) 個棧的頂部 \(x\) 個球,並求出最後一個球的顏色。
- 將第 \(u\) 個棧的球依次彈出並壓入 \(v\) 中。
思路
這裡主要是第三個操作最難處理。第三個操作很明顯可以用啟發式合併解決,但是它在彈出和壓入時會進行反轉,所以我們可以對每個棧記錄其有沒有反轉過,如果反轉了則壓入和刪除都要從棧底進行,所以改用雙端佇列即可。
空間複雜度 \(O(N+M)\),時間複雜度 \(O((N+M)\log N)\)。
程式碼
#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
const int MAXN = 200001;
int n, m;
bool vis[MAXN];
deque<pii> que[MAXN];
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
for(int i = 1, x, y, z; i <= m; ++i) {
string op;
cin >> op >> x >> y;
if(op == "push") {
cin >> z;
if(!vis[z]) {
que[z].push_front({y, x});
}else {
que[z].push_back({y, x});
}
}else if(op == "pop") {
int ans = 0;
for(; x; ) {
if(!vis[y]) {
auto &[a, b] = que[y].front();
ans = a;
if(b <= x) {
x -= b;
que[y].pop_front();
}else {
b -= x;
break;
}
}else {
auto &[a, b] = que[y].back();
ans = a;
if(b <= x) {
x -= b;
que[y].pop_back();
}else {
b -= x;
break;
}
}
}
cout << ans << "\n";
}else if(op == "put") {
if(que[x].size() < que[y].size()) {
for(; !que[x].empty(); ) {
if(!vis[x]) {
auto [a, b] = que[x].front();
if(!vis[y]) {
que[y].push_front({a, b});
}else {
que[y].push_back({a, b});
}
que[x].pop_front();
}else {
auto [a, b] = que[x].back();
if(!vis[y]) {
que[y].push_front({a, b});
}else {
que[y].push_back({a, b});
}
que[x].pop_back();
}
}
}else {
swap(que[x], que[y]);
swap(vis[x], vis[y]);
for(; !que[x].empty(); ) {
if(!vis[x]) {
auto [a, b] = que[x].front();
if(!vis[y]) {
que[y].push_front({a, b});
}else {
que[y].push_back({a, b});
}
que[x].pop_front();
}else {
auto [a, b] = que[x].back();
if(!vis[y]) {
que[y].push_front({a, b});
}else {
que[y].push_back({a, b});
}
que[x].pop_back();
}
}
vis[y] ^= 1;
}
}
}
return 0;
}