題目描述
阿爾比恩王國(the Albion Kingdom)潛伏着一羣代號“白鴿隊(Team White Pigeon)”的間諜。在沒有任務的時候,她們會進行各種各樣的訓練,比如快速判斷一個文檔有沒有語法錯誤,這有助於她們鑑別寫文檔的人受教育程度。
這次用於訓練的是一個含有n個括號的文檔。括號一共有mm種,每種括號都有左括號和右括號兩種形式。我們定義用如下的方式定義一個合法的文檔:
1.一個空的字符串是一個合法的文檔。
2.如果A,B都是合法的文檔,那麼AB也是合法的文檔。
3.如果S是合法的文檔,那麼aSb也是合法的文檔,其中a,b是同一種括號,並且a是左括號,b是右括號。
現在給出q個詢問,每次詢問只考慮文檔第ll至rr個字符的情況下,文檔是不是合法的。
輸入
第一行兩個整數n,m,q(1≤n,m,q≤106)。
第二行有n個空格隔開的整數x,第i個整數xi(0≤xi<m∗2)代表文檔中的第i個字符是第⌊x/2⌋種括號,且如果xi是偶數,它代表一個左括號,否則它代表一個右括號。
接下來q行,每行兩個空格隔開的整數l,r(1≤l≤r≤n),代表詢問第l至r個字符構成的字符串是否是一個合法的文檔。
輸出
輸出共q行,如果詢問的字符串是一個合法的文檔,輸出"Yes",否則輸出"No"。
樣例輸入
6 4 3 0 2 3 1 4 7 1 4 1 5 5 6
樣例輸出
Yes No No
我的思路是每次讀入一個括號,用括號序列的思路,如果棧頂和當前括號不能匹配,則將當前括號壓入棧;如果能匹配,那麼就將棧頂元素彈出。並且每次讀入處理完之後都將當前棧頂元素存入一個ans數組內。很明顯,如果l位置與r位置是匹配的括號,並且從l位置到r位置中間均爲合法序列,那麼從l+1位置到r-1位置的括號序列必然合法,也就是說中間這段的括號序列左半邊所對應的右半邊必然也在這段範圍之內,那麼我們在預處理的時候一定在l之後將左括號壓入了棧,並在遇到左括號所對應的右括號時從棧中彈出,那麼r位置與l-1位置時棧頂元素相同,即ans[l]==ans[r-1]。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
int top;
int z[maxn],st[maxn],ans[maxn];
int main()
{
int n,m,q,l,r;
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; ++i)
scanf("%d", &z[i]);
for (int i = 1; i <= n; ++i)
{
if (!top || z[st[top]] / 2 != z[i] / 2 || z[i] != z[st[top]] + 1) //如果當前位置與棧頂位置的括號不匹配或者不合法
st[++top] = i;
else //如果當前位置與棧頂位置的括號相匹配並且合法
--top;
ans[i] = st[top]; //存下棧頂位置
}
while (q--)
{
scanf("%d%d", &l, &r);
if (ans[r] == ans[l - 1])
puts("Yes");
else
puts("No");
}
return 0;
}