Serejaとブラケット
トピックリンク:codeforces - 380C
Serejaブラケット配列を有するS 1は、 sは、2 ...、* ** N S個、又は、換言すれば、文字列の長さの* nは、文字からなる"("および")"。
Serejaが応答する必要がm個のクエリを、それらの各々は、二つの整数で記述さL 、I 、 R iは(1≤ L iは ≤ rが iは ≤ N)。答えI番目のクエリは、シーケンスの最大正しいブラケットサブシーケンスの長さS L、I、 S 、L I + 1、...、 S R I。Serejaは、すべてのクエリに答えます。
あなたはノートにサブシーケンスの定義や正しいブラケットシーケンスを見つけることができます。
入力
最初の行は、文字のシーケンス含まS、1 だ 2、...、*(1≤* N ** sは N スペースなしで106≤)。各文字は、A「(」またはA「)」のいずれかです。2行目は整数含まM(1≤ M クエリの数- 105≤)を。次の各m個の行は、整数の対を含んでいます。I番目の行は、整数含まL 、I 、 R I(1≤ L iは ≤ Rを iは ≤ Nの説明- )I番目のクエリを。
出力
単一ライン上の各質問への回答を印刷します。彼らは、入力に行くために、答えを印刷します。
例
入力
())(())(())(71 12 31 21 128 125 112 10
出力
00210466
注意
長さのサブ| X | 文字列のS = S 1 、S 2 ... S | S | (ここで、| S |の文字列の長さSが)文字列であり、X = S K 1 S K 2 ... S * ** K | X | (1≤ K 1 < K 2 <... < K | X |≤| S * |)。
正しいブラケット配列は、文字を挿入することにより、正しいaryphmetic表現に変換することができるブラケット配列である「1」と「+」の文字列の文字の間です。例えば、ブラケット配列 "()()"、 "(())、" 正しい(得られた式 "(1)+(1)"、 "((1 + 1)+1)")、及び「) (」および 『(』ではありません。
第三のクエリのために必要なシーケンスは«()»となります。
第四のクエリのために必要なシーケンスは«()(())(())»となります。
質問の意味:
あなただけの文字列を与える「(」と「」)、および
そして、クエリq、二つの整数のそれぞれは、LとRにあなたを依頼するには、間隔を表します。あなたは、出力間隔を選択できるように、それぞれのお問い合わせは、最も長いシーケンスの正当な括弧配列の長さです。
アイデア:
お問い合わせの間隔は、右端に昇順に並べ替え、オフラインで保存されました
次に、(下付き文字に一致しない維持するために、スタックとそれぞれを右スキャンを取り、
時間のA)文字に来て、そのこと(アレイのツリーと同時にスタックの一致トップ、(目標値+2
間隔は、各区間の右端ポイントを来たときに答えが更新されます。
なぜあなたはそれを書くことができますか?
私たちは分析して間隔の各文字列)文字のために固定することができることを見出し可能性があるので(これまでに正しい答えのセクションを一致させます。
詳細コードを参照してください。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node {
int l, r;
int id;
} a[maxn];
char s[maxn];
int n;
int m;
bool cmp(node aa, node bb)
{
return aa.r < bb.r;
}
int tree[maxn];
int lowbit(int x)
{
return x & (-1 * x);
}
void add(int x, int val)
{
while (x <= n) {
tree[x] += val;
x += lowbit(x);
}
}
int ask(int x)
{
int res = 0;
while (x) {
res += tree[x];
x -= lowbit(x);
}
return res;
}
int ans[maxn];
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
gbtb;
cin >> s + 1;
n=strlen(s+1);
cin >> m;
repd(i, 1, m ) {
cin >> a[i].l >> a[i].r;
a[i].id = i;
}
sort(a + 1, a + 1 + m, cmp);
stack<int> st;
while (sz(st)) {
st.pop();
}
int pos = 1;
repd(i, 1, m) {
// chu(pos);
repd(j, pos, a[i].r) {
if (s[j] == '(') {
st.push(j);
} else {
if (sz(st)) {
add(st.top(), 2);
st.pop();
}
}
}
ans[a[i].id] = ask(a[i].r) - ask(a[i].l - 1);
pos = a[i].r + 1;
}
repd(i,1,m)
{
printf("%d\n",ans[i] );
}
return 0;
}
inline void getInt(int *p)
{
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
} else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}