一眼线段树!
对线段树掌握不熟练的同学直接暴力!
这代码我敲了一个小时!
import java.util.*;
import java.io.*;
public class Main {
static int N = 1000010, INF = 1 << 29;
static class Node {
int l, r;
int min;
int max;
int sum;
int lazy = 1; // 是否翻转 -1:no 1:yes
int add;
public Node(int a, int b) {
l = a; r = b;
}
}
static Node tr[] = new Node[N << 2];
static int a[] = new int[N], s[] = new int[N];
static int n, m;
static void F1(int u) {
tr[u].add *= -1;
tr[u].lazy *= -1;
tr[u].sum *= -1;
tr[u].max = -tr[u].max;
tr[u].min = -tr[u].min;
int t = tr[u].max;
tr[u].max = tr[u].min;
tr[u].min = t;
}
static void F2(int u, int val) {
tr[u].add += val;
tr[u].min += val;
tr[u].max += val;
}
static void build(int u, int l, int r) {
tr[u] = new Node(l, r);
if(l == r) {
tr[u].min = tr[u].max = s[l];
tr[u].sum = a[l];
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
static void pushup(int u) {
tr[u].min = Math.min(tr[u << 1].min, tr[u << 1 | 1].min);
tr[u].max = Math.max(tr[u << 1].max, tr[u << 1 | 1].max);
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
static void pushdown(int u) {
if(tr[u].lazy == -1) {
F1(u << 1);
F1(u << 1 | 1);
tr[u].lazy = 1;
}
if(tr[u].add != 0) {
F2(u << 1, tr[u].add);
F2(u << 1 | 1, tr[u].add);
tr[u].add = 0;
}
}
static int query_sum(int u, int l, int r) {
if(tr[u].l >= l && tr[u].r <= r)
return tr[u].sum;
int res = 0;
int mid = tr[u].l + tr[u].r >> 1;
pushdown(u);
if(l <= mid) res += query_sum(u << 1, l, r);
if(r > mid) res += query_sum(u << 1 | 1, l, r);
return res;
}
static int query_min(int u, int l, int r) {
// System.out.println(u + " " + l + " " + r);
if(tr[u].l >= l && tr[u].r <= r) {
return tr[u].min;
}
int mid = tr[u].l + tr[u].r >> 1;
int res = INF;
pushdown(u);
if(l <= mid)
res = query_min(u << 1, l, r);
if(r > mid) res = Math.min(res, query_min(u << 1 | 1, l, r));
return res;
}
static int query_find(int u, int l, int r, int val) {
if(tr[u].l == tr[u].r) {
return tr[u].l;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(tr[u << 1 | 1].min <= val)
return query_find(u << 1 | 1, l, r, val);
if(l <= mid)
return query_find(u << 1, l, r, val);
return 0;
}
static boolean check(int l, int r, int pre) {
return query_min(1, l, l + r) >= pre;
}
static void modify_rev(int u, int l, int r) {
if(tr[u].l >= l && tr[u].r <= r) {
F1(u);
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) modify_rev(u << 1, l, r);
if(r > mid) modify_rev(u << 1 | 1, l, r);
pushup(u);
}
static void modify_add(int u, int l, int r, int val) {
if(tr[u].l >= l && tr[u].r <= r) {
F2(u, val);
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) modify_add(u << 1, l, r, val);
if(r > mid) modify_add(u << 1 | 1, l, r, val);
pushup(u);
}
static void change(int l, int r) {
int add1 = query_sum(1, 1, r) * -2;
modify_rev(1, 1, r);
if(r + 1 <= n) {
modify_add(1, r + 1, n, add1);
}
if(l - 1 >= 1) {
int add2 = query_sum(1, 1, l - 1) * -2;
modify_rev(1, 1, l - 1);
modify_add(1, l, n, add2);
}
}
public static void main(String[] args) {
IR sc = new IR();
n = sc.nextInt();
m = sc.nextInt();
String ss = sc.next();
for(int i = 0; i < n; i ++ ) {
if(ss.charAt(i) == '(') {
a[i + 1] = 1;
}
else a[i + 1] = -1;
s[i + 1] = s[i] + a[i + 1];
}
build(1, 1, n);
while(m -- > 0) {
int op = sc.nextInt();
if(op == 1) {
int l = sc.nextInt();
int r = sc.nextInt();
change(l, r);
} else {
int L = sc.nextInt();
if(query_sum(1, L, L) == -1) {
System.out.println(0);
continue;
}
int l = 1, r = n - L, res = 0;
int pre = 0;
if(L != 1) pre = query_min(1, L - 1, L - 1);
while(l <= r) {
int mid = l + r >> 1;
// System.out.println(mid + " " + l + " " + r);
if(check(L, mid, pre)) {
l = mid + 1;
res = mid;
}
else r = mid - 1;
}
if(res + L < n) {
System.out.println(L + res);
continue;
}
int ans = query_find(1, L, n, pre);
if(ans != L) System.out.println(ans);
else System.out.println(0);
}
}
}
}
class IR {
BufferedReader br;
StringTokenizer st;
IR() {
br = new BufferedReader(new InputStreamReader(System.in));
}
boolean hasNext() {
while(st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
return false;
}
}
return true;
}
String next() {
if(hasNext()) return st.nextToken();
return null;
}
int nextInt() {
return Integer.parseInt(next());
}
}