线段树维护区间括号序列合法性

 

[ABC223F] Parenthesis Checking

维护区间和以及前缀最小值, 对于一个区间括号序列合法判断方法 :

视 ' ( ' 为 1 , ' ) ' 为 -1

那么一段区间括号序列合法就是:
1.该段区间和为 0
2.对于这段中每个位置的前缀和 u 都要满足 u >= 0

 

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;

const int N = 2e5 + 10;

int v[N], all, minx;

struct Info {
    int sum, minn;
};

struct node{
    Info info;
} Seg[N * 4];

Info operator + (const Info &l, const Info &r) {
    Info ans; ans.sum = l.sum + r.sum;
    ans.minn = min(l.minn, l.sum + r.minn);
    return ans;
}

void pushup(int id) {
    Seg[id].info = Seg[id * 2].info + Seg[id * 2 + 1].info;
}

void build(int id, int l, int r) {
    if(l == r) {
        Seg[id].info.sum = Seg[id].info.minn = v[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(id * 2, l, mid); build(id * 2 + 1, mid + 1, r);
    pushup(id);
}

void modify(int id, int l, int r, int pos, int val) {
    if(l == r) {
        Seg[id].info.sum = Seg[id].info.minn = val;
        return;
    }
    int mid = (l + r) >> 1;
    if(pos <= mid) modify(id * 2, l, mid, pos, val);
    else modify(id * 2 + 1, mid + 1, r, pos, val);
    pushup(id);
}

void qurey(int id, int l, int r, int x, int y) {
    if(l >= x && r <= y) {
        minx = min(minx, all + Seg[id].info.minn);
        all += Seg[id].info.sum;
        return;
    }    
    int mid = (l + r) >> 1;
    if(x <= mid) qurey(id * 2, l, mid, x, y);
    if(y > mid) qurey(id * 2 + 1, mid + 1, r, x, y);
}

int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n, q; cin >> n >> q;
    string s; cin >> s;
    for(int i = 0; i < n; i++) {
        if(s[i] == '(') v[i + 1] = 1;
        else v[i + 1] = -1;
    }
    build(1, 1, n);
    while(q--) {
        int op, l, r; cin >> op >> l >> r;
        if(op == 1) {
            if(s[l - 1] == s[r - 1]) continue;
            if(s[l - 1] == '(') modify(1, 1, n, l, -1), modify(1, 1, n, r, 1);
            else modify(1, 1, n, l, 1), modify(1, 1, n, r, -1);
            swap(s[l - 1], s[r - 1]);
        } else {
            minx = INT_MAX, all = 0;
            qurey(1, 1, n, l, r);
            // cout << all << ' ' << minx << endl; 
            if(all == 0 && minx == 0) cout << "Yes" << endl;
            else cout << "No" << endl;
        }
    }

    return 0;
}
View Code

Editor

 合法性判断和上题一样, 对于嵌套括号其实就是前缀最大值,此时我们只需要线段树多维护一个前缀最大值即可

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
typedef long long ll;

const int N = 1e6 + 10;

struct Info {
    int sum, minn, maxn;
};

struct node{
    Info info;
} Seg[N * 4];

Info operator + (const Info &l, const Info &r) {
    Info ans; ans.sum = l.sum + r.sum;
    ans.minn = min(l.minn, l.sum + r.minn);
    ans.maxn = max(l.maxn, l.sum + r.maxn);
    return ans;
}

void pushup(int id) {
    Seg[id].info = Seg[id * 2].info + Seg[id * 2 + 1].info;
}

void modify(int id, int l, int r, int pos, int val) {
    if(l == r) {
        Seg[id].info.sum = Seg[id].info.minn = Seg[id].info.maxn = val;
        return;
    }
    int mid = (l + r) >> 1;
    if(pos <= mid) modify(id * 2, l, mid, pos, val);
    else modify(id * 2 + 1, mid + 1, r, pos, val);
    pushup(id);
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n; cin >> n;
    string s; cin >> s;
    int pos = 1, maxpos = 1;
    for(int i = 0; i < n; i++) {
        maxpos = max(maxpos, pos);
        if(s[i] == 'R') pos++;
        if(s[i] == 'L') pos--;
        maxpos = max(maxpos, pos);
    }
    pos = 1;
    for(int i = 0; i < n; i++) {
        if(s[i] == 'R') {
            pos++;
        } else if(s[i] == 'L') {
            if(pos != 1) pos--;
        } else if(s[i] == '(') {
            modify(1, 1, maxpos, pos, 1);
        } else if(s[i] == ')') {
            modify(1, 1, maxpos, pos, -1);
        } else {    
            modify(1, 1, maxpos, pos, 0);
        }
        if(Seg[1].info.sum == 0 && Seg[1].info.minn == 0) {
            cout << Seg[1].info.maxn << ' ';
        } else {
            cout << -1 << ' ';
        }
    }
    return 0;
}
View Code

BRCKTS - Brackets

 

板子题, 最简单的一题

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
typedef long long ll;

const int N = 3e4 + 10;

int minx, all, v[N];

struct Info {
    int sum, minn, maxn;
};

struct node{
    Info info;
} Seg[N * 4];

Info operator + (const Info &l, const Info &r) {
    Info ans; ans.sum = l.sum + r.sum;
    ans.minn = min(l.minn, l.sum + r.minn);
    return ans;
}

void pushup(int id) {
    Seg[id].info = Seg[id * 2].info + Seg[id * 2 + 1].info;
}

void build(int id, int l, int r) {
    if(l == r) {
        Seg[id].info.sum = Seg[id].info.minn = v[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(id * 2, l, mid); build(id * 2 + 1, mid + 1, r);
    pushup(id);
}

void modify(int id, int l, int r, int pos, int val) {
    if(l == r) {
        Seg[id].info.sum = Seg[id].info.minn = val;
        return;
    }
    int mid = (l + r) >> 1;
    if(pos <= mid) modify(id * 2, l, mid, pos, val);
    else modify(id * 2 + 1, mid + 1, r, pos, val);
    pushup(id);
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    for(int T = 1; T <= 10; T++) {
        cout << "Test " << T << ":" << endl;
        int n; cin >> n;
        string s; cin >> s; s = " " + s;
        for(int i = 1; i <= n ; i++) {
            if(s[i] == '(') v[i] = 1;
            else v[i] = -1;
        }
        build(1, 1, n);
        int q; cin >> q;
        while(q--) {
            int op; cin >> op;
            if(op == 0) {
                if(Seg[1].info.sum == 0 && Seg[1].info.minn >= 0) cout << "YES" << endl;
                else cout << "NO" << endl;
            } else {
                if(s[op] == '(') {
                    modify(1, 1, n, op, -1);
                    s[op] = ')';
                } else {
                    modify(1, 1, n, op, 1);
                    s[op] = '(';
                }
            }
        }
    }
    return 0;
}
View Code
posted @ 2023-10-12 22:44  zhujio  阅读(33)  评论(0编辑  收藏  举报