湖南省第十二届大学生计算机程序设计竞赛 G Parenthesis

1809: Parenthesis

Description

Bobo has a balanced parenthesis sequence P=p1 p2…pn of length n and q questions.

The i-th question is whether P remains balanced after pai and pbi  swapped. Note that questions are individual so that they have no affect on others.

Parenthesis sequence S is balanced if and only if:

1. S is empty;

2. or there exists balanced parenthesis sequence A,B such that S=AB;

3. or there exists balanced parenthesis sequence S‘ such that S=(S‘).

Input

The input contains at most 30 sets. For each set:

The first line contains two integers n,q (2≤n≤105,1≤q≤105).

The second line contains n characters p1 p2…pn.

The i-th of the last q lines contains 2 integers ai,bi (1≤ai,bi≤n,ai≠bi).

Output

For each question, output "Yes" if P remains balanced, or "No" otherwise.

Sample Input

4 2
(())
1 3
2 3
2 1
()
1 2

Sample Output

No
Yes
No

HINT

题意:

  给你长度n的合法括号匹配和q个询问

  每次询问你 交换ai,bi两个位置的符号,交换后是否还是合法的

题解:

  分块

  (转化为1,)转化为-1

  合法括号序列满足前缀和永远大于等于0

  利用这个每次修改两个位置

  维护这个关系就好了

  分块可过的

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair

typedef long long LL;
const long long INF = 1e18;
const double Pi = acos(-1.0);
const int N = 2e5+10, M = 1e6+11, mod = 1e6+3, inf = 5000;

int block,n,q,m;
int sum[N],pos[N],mi[N],a[N],b[N],add[N],f[N];
char ch[N];
void init() {
        int s = 0;
        pos[0] = 0;
        memset(b,0,sizeof(b));
        memset(sum,0,sizeof(sum));
        memset(add,0,sizeof(add));
        for(int i = 1; i <= n; ++i) b[i] = a[i];
        for(int i = 1; i <= n; ++i) sum[i] = sum[i-1] + b[i];
        for(int i = 0; i < N; ++i) mi[i] = inf;
        for(int i = 1; i <= n; ++i) {
            if(pos[i] != pos[i-1]) s = 0;
            s += b[i];
            mi[pos[i]] = min(mi[pos[i]],s);
        }
        for(int i = 1; i <= n; ++i) add[pos[i]] += b[i];
        f[0] = 1;
        s = 0;
        for(int i = 1; i <= n; ++i) {
            s+=b[i];
            if(s < 0) f[i] = 0;
            else f[i] = f[i-1];
        }
}
int solve(int l,int r) {
        int OK = 1;
        swap(b[l],b[r]);
        if(pos[l] == pos[r]) {
                int s = sum[block * (pos[l]-1)];
                for(int i = block * (pos[l]-1) + 1; i <= min(pos[l] * block,n); ++i) {
                    s += b[i];
                    if(s < 0) OK = 0;
                }
                for(int i = pos[l]+1; i <= m; ++i) {
                    if(s + mi[i] < 0) OK = 0;
                    s += (add[i]);
                }if(s < 0) OK = 0;
        } else {
                int s = sum[block * (pos[l]-1)];
                for(int i = block*(pos[l]-1) + 1; i <= min(pos[l] * block,n); ++i) {
                    s += b[i];
                    if(s < 0) OK = 0;
                }
                for(int i = pos[l]+1; i <= pos[r]-1; ++i) {
                    if(s + mi[i] < 0) OK = 0;
                    s += (add[i]);
                }
                for(int i = block * (pos[r]-1) + 1; i <= min(pos[r]*block,n); ++i) {
                    s += b[i];
                    if(s < 0) OK = 0;
                }
                  for(int i = pos[r]+1; i <= m; ++i) {
                    if(s + mi[i] < 0) OK = 0;
                    s += (add[i]);
                }
        }
        swap(b[l],b[r]);
        if(OK == 1) return 1;
        else return 0;
}
int main() {
        while(scanf("%d%d",&n,&q)!=EOF) {
            scanf("%s",ch);
            block = int(sqrt(n));
            memset(a,0,sizeof(a));
            memset(pos,0,sizeof(pos));
            for(int i = 1; i <= n; i++) {if(ch[i-1] == ‘(‘) a[i] = 1; else a[i] = -1; pos[i]=(i-1)/block+1;}
            if(n%block) m = n/block + 1; else m = n/block;
            init();
            for(int i = 1; i <= q; ++i) {
                int l,r;
                scanf("%d%d",&l,&r);
                if(l > r) swap(l,r);
                if(solve(l,r) == 1) printf("Yes\n");
                else printf("No\n");
            }
        }
        return 0;
}
 
时间: 2024-11-05 13:47:16

湖南省第十二届大学生计算机程序设计竞赛 G Parenthesis的相关文章

2016年湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)

原题链接 http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1809 Description Bobo has a balanced parenthesis sequence P=p1 p2…pn of length n and q questions. The i-th question is whether P remains balanced after pai and pbi  swapped. Note that questions ar

湖南省第十二届大学生计算机程序设计竞赛 problem A 2016

如果 a * b % 2016 == 0 如果a = 1 ,且 a * b % 2016 == 0 考虑一下a = 2017的时候 2017 * b = (2016 + 1) * b % 2016 == 0必定成立 那么就是说1中搭配成的b,2017一样能搭配. 同样:4033 * b = (2016 + 2016 + 1) * b % 2016 == 0必定成立 所以,我可以枚举[1,2016]中[1,2016]中,i * j % 2016 == 0的对数,然后乘上对应的[1,n]中有i这个数

2016年湖南省第十二届大学生计算机程序设计竞赛Problem A 2016 找规律归类

Problem A: 2016 Time Limit: 5 Sec  Memory Limit: 128 MB Description 给出正整数 n 和 m,统计满足以下条件的正整数对 (a,b) 的数量: 1. 1≤a≤n,1≤b≤m; 2. a×b 是 2016 的倍数. Input 输入包含不超过 30 组数据. 每组数据包含两个整数 n,m (1≤n,m≤109). Output 对于每组数据,输出一个整数表示满足条件的数量. Sample Input 32 63 2016 2016

CSU 1803 2016(同余公式)2016年湖南省第十二届大学生计算机程序设计竞赛

题意给出正整数 n 和 m,统计满足以下条件的正整数对 (a,b) 的数量:1. 1 ≤ a ≤ n, 1 ≤ b ≤ m;2. a×b 是 2016 的倍数. 样例输入32 632016 20161000000000 1000000000 样例输出1305767523146895502644 思路由同余公式可得a * b % 2016 = (a % 2016) * (b % 2016) % 2016所以如果 x*y 是2016的倍数的话,那么(2016*k + x)*y也是那么只需要统计1-n

湖南省第十二届大学生计算机程序设计竞赛 A 2016

1803: 2016 Description 给出正整数 n 和 m,统计满足以下条件的正整数对 (a,b) 的数量: 1. 1≤a≤n,1≤b≤m; 2. a×b 是 2016 的倍数. Input 输入包含不超过 30 组数据. 每组数据包含两个整数 n,m (1≤n,m≤109). Output 对于每组数据,输出一个整数表示满足条件的数量. Sample Input 32 63 2016 2016 1000000000 1000000000 Sample Output 1 30576 7

【数学】CSU 1810 Reverse (2016湖南省第十二届大学生计算机程序设计竞赛)

题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1810 题目大意: 一个长度为N的十进制数,R(i,j)表示将第i位到第j位翻转过来后的数字,求mod 109+7 题目思路: [数学] 这题换一种思路,看每个数字能够对答案的贡献情况.(可以手推01,10,001,010,100.....,也可以像我一样写个暴力打个10以内的表看看规律) 现在先考虑位置为i的数字为1的情况(最后乘上这个数字就行).可以发现贡献是对称的(第i位的1和第

【模拟】【数学】CSU 1803 2016 (2016湖南省第十二届大学生计算机程序设计竞赛)

题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1803 题目大意: 给定n,m(n,m<=109)1<=i<=n,1<=j<=m,求i*j%2016=0的方案数. 题目思路: [模拟][数学] 按照%2016的余数分类.每增加一个2016就又多一种方案.统计是2016的几倍,根据余数分类.最后枚举i,j的余数即可求解. 1 // 2 //by coolxxx 3 //#include<bits/stdc++

【拓扑】【宽搜】CSU 1084 有向无环图 (2016湖南省第十二届大学生计算机程序设计竞赛)

题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1804 题目大意: 一个有向无环图(DAG),有N个点M条有向边(N,M<=105),每个点有两个值ai,bi(ai,bi<=109),count(i,j)表示从i走到j的方案数. 求mod 109+7的值. 题目思路: [拓扑][宽搜] 首先将式子拆开,每个点I走到点J的d[j]一次就加上一次ai,这样一个点被i走到的几次就加上几次ai,相当于count(i,j)*ai,最终只要求

【模拟】CSU 1807 最长上升子序列~ (2016湖南省第十二届大学生计算机程序设计竞赛)

题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1807 题目大意: 给你一个长度为N(N<=105)的数列,数列中的0可以被其他数字替换,最终形成一个1~N的排列,求这个排列的最长上升子序列长度为N-1的方案数. 题目思路: [模拟] 这道题需要分类讨论. 首先可以肯定,一个长度为n的序列最长上升子序列长度为n-1(最长下降子序列长度为2),那么这个序列的样子是1~n从小到大排列后其中一个数字挪到其余数字中间(错位) 一个长度为L的