您的位置:首页 > 其它

CodeForces 380.C Sereja and Brackets

2014-01-14 23:39 302 查看

题意

一串括号序列,只由(和)组成,然后是m个提问,提问l和r区间内,最大的匹配匹配括号数。

思路

第一,贪心的思想,用最正常的方式去尽量匹配,详细点说就是,先找到所有的(),然后删除这些(),再找所有的()。用这种方式匹配出来的,就是最优的方案。

第二,如果我们把所有的'('当成+1, ')'当成-1, 然后画成函数,那么,我们可以通过函数的图像,来得到得到,这段区间的长度(r-l),这段区间的最小值(min),这段区间没用的')'的数量(f(l)-min),这段区间没用的'('的数量(f(r)-f(l)+(f(l)-min)) 然后就得到解了。

另外,区间查询最小值,用线段树就行。

本解 最重要的地方,在于通过函数图像得到解。最难得的就是如果通过函数图像得到解,唉,谁知道呢= =……

我的代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1020000
#define lson(A) ((A)<<1)
#define rson(A) ((A)<<1|1)

int top;

char str
;
int sum
;

int tree[N<<2];

void init(int root, int l, int r) {
if (l == r) {
tree[root] = sum[l];
return;
}
int mid = (l+r)/2;
init(lson(root), l, mid);
init(rson(root), mid+1, r);
tree[root] = min(tree[lson(root)], tree[rson(root)]);
}

int query(int root, int rl, int rr, int ql, int qr) {
if (root == -1) exit(-1);
//printf("%d, %d %d %d %d\n", root, rl, rr, ql ,qr);
if ((rl == ql && rr == qr) || rl==rr) {
return tree[root];
}
int mid = (rl+rr)/2;
if (mid < ql) return query(rson(root), mid+1, rr, ql, qr);
if (qr <= mid) return query(lson(root), rl, mid, ql, qr);
else if (ql <= mid && mid+1 <= qr)
return min( query(lson(root), rl, mid, ql, min(mid, qr))
,query(rson(root), mid+1, rr, max(mid+1, ql), qr));
else exit(-1);
}

int main() {
scanf("%s", str);
sum[0] = 0;
int i;
for (i = 0; str[i]; i++) {
sum[i+1] = sum[i] + (str[i] == '(' ? 1 : -1 );
}
int len = i;
init(1, 0, len);

int m;
scanf("%d", &m);
while (m--) {
int l, r;
scanf("%d%d", &l, &r);
l--;
int minnum = query(1, 0, len, l, r);
int skipClose = sum[l] - minnum;
int skipOpen = sum[r]-sum[l]+skipClose;
//printf("(%d, %d,%d)\n", minnum, skipClose, skipOpen);
printf("%d\n", r-l-skipClose-skipOpen);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: