[BZOJ2329][HNOI2011]括号修复 平衡树

n2 暴力能AC,类似贪心的做法,直接扫一遍就可以
诶这题目平方暴力能跑过去
只能说出题人出的数据出得真得很差,非常不用心
这种数据在比赛里对公平是多么大的一种破坏
希望比赛的出题人能够严肃地对待自己出的题目
若没有能力出好这题的数据请不要出这种题目

#include <bits/stdc++.h>
#define N 100050
using namespace std;
inline int rd() { int r; scanf("%d",&r); return r; }
int a[N],n,m,l,r;
char s[N],c[10];
int main() {
    n = rd(), m = rd();
    scanf("%s",s+1);
    for (int _=1;_<=n;_++) a[_] = s[_] == '(' ? 1 : -1;
    while (m--) {
        scanf("%s",s+1);
        l = rd(), r = rd();
        if (s[1] == 'R') {
            scanf("%s",c+1);
            for (int i=l;i<=r;i++) a[i] = c[1] == '(' ? 1 : -1;
        }
        if (s[1] == 'S') {
            int len = (r-l+1) >> 1;
            for (int i=1;i<=len;i++) swap(a[l+i-1], a[r-i+1]);
        }
        if (s[1] == 'I') {
            for (int i=l;i<=r;i++) a[i] = -a[i];
        }
        if (s[1] == 'Q') {
            int cnt=0, ans=0;
            for (int i=l;i<=r;i++) {
                cnt += a[i];
                if (cnt < 0) ans++, cnt += 2;
            }
            while (cnt > 0) cnt-=2 , ans++;
            printf("%d\n",ans);
        }
    }
    return 0;
}

标准解法就暴力放到支持区间操作的平衡树上就行了

#include <bits/stdc++.h>
#define N 100050 
using namespace std;
//splay

#define MP make_pair
#define x first
#define y second
typedef pair<int,int> pii;
struct Node{
    int a,siz,sum,max[2],min[2];
    int cov,swp,inv;
    pii ans[4];
}tr[N];
int s[N][2],fa[N],a[N],d[N],n,m,cnt,rt;
char st[N];

// 0  无,  无
// 1取反,  无
// 2  无,翻转 
// 3取反,翻转 
inline void utax(int &x,int y) { x = max(x,y); }
inline void utin(int &x,int y) { x = min(x,y); }
inline int rd() { int r; scanf("%d",&r); return r; }

#define O tr[t]
#define L tr[ s[t][0] ]
#define R tr[ s[t][1] ]

void update(int t) {
    O.siz = L.siz + R.siz + 1;
    O.sum = L.sum + R.sum + O.a;

    O.max[0] = L.sum + O.a;
    utax(O.max[0], L.max[0]);
    utax(O.max[0], L.sum + O.a + R.max[0]);

    O.max[1] = R.sum + O.a;
    utax(O.max[1], R.max[1]);
    utax(O.max[1], R.sum + O.a + L.max[1]);

    O.min[0] = L.sum + O.a;
    utin(O.min[0], L.min[0]);
    utin(O.min[0], L.sum + O.a + R.min[0]);

    O.min[1] = R.sum + O.a;
    utin(O.min[1], R.min[1]);
    utin(O.min[1], R.sum + O.a + L.min[1]);

    for (int _=0,tmp=-1;_<4;_++) {
        O.ans[_].x = _<2 ? L.ans[_].x : R.ans[_].x;
        int cur  = _<2 ? L.ans[_].y : R.ans[_].y;
        cur += (_&1) ? -O.a : O.a;
        cur < 0 ? O.ans[_].x++,cur+=2 : 0;
        _ == 0 ? tmp = cur+R.min[0], cur+=R.sum : 0;
        _ == 1 ? tmp = cur-R.max[0], cur-=R.sum : 0;
        _ == 2 ? tmp = cur+L.min[1], cur+=L.sum : 0;
        _ == 3 ? tmp = cur-L.max[1], cur-=L.sum : 0;
        -tmp > 0 ? O.ans[_].x += (-tmp+1)>>1, cur += ( (-tmp+1)>>1 ) << 1 : 0;
        O.ans[_].y = cur;
    }

    return ;
} 

int color(int t,int t1,int t2,int t3) {
    if (!t1 && !t2 && !t3) return 0;
    if (t1) {
        O.a = t1;
        O.sum = O.siz * t1;
        O.max[0] = O.max[1] = max(0, O.sum);
        O.min[0] = O.min[1] = min(0, O.sum);
        O.cov = t1;
        O.swp = 0, O.inv = 0;
        if (t1 > 0) {
            O.ans[0] = O.ans[2] = MP(0,O.siz);
            O.ans[1] = O.ans[3] = MP((O.siz+1)>>1, O.siz&1);
        } else {
            O.ans[1] = O.ans[3] = MP(0,-O.sum);
            O.ans[0] = O.ans[2] = MP((-O.sum+1)>>1, O.siz&1);
        }
    }
    if (t2) {
        swap(s[t][0], s[t][1]);
        swap(O.ans[0], O.ans[2]);
        swap(O.ans[1], O.ans[3]);
        swap(O.max[0], O.max[1]);
        swap(O.min[0], O.min[1]);
        tr[t].swp ^= 1;
    }
    if (t3) {
        tr[t].a = -tr[t].a; tr[t].sum = -tr[t].sum;
        swap(tr[t].max, tr[t].min);
        tr[t].max[0] = -tr[t].max[0];
        tr[t].max[1] = -tr[t].max[1];
        tr[t].min[0] = -tr[t].min[0];
        tr[t].min[1] = -tr[t].min[1];
        swap(O.ans[0], O.ans[1]);
        swap(O.ans[2], O.ans[3]);
        tr[t].inv  ^= 1;
    }
    return 0;
} 

void rotate(int x,int &k) {
    int y = fa[x] , z = fa[y] , l = (s[y][0] == x) ^ 1 ,r = l ^ 1;
    if (y == k) k = x; else {
        if (s[z][0] == y) s[z][0] = x; else s[z][1] = x;
    }
    s[y][l] = s[x][r]; s[x][r] = y;
    fa[y] = x; fa[x] = z; fa[ s[y][l] ] = y;
    update(y), update(x);
}

void push_down(int t) {
    if (s[t][0]) color(s[t][0], tr[t].cov, tr[t].swp, tr[t].inv);
    if (s[t][1]) color(s[t][1], tr[t].cov, tr[t].swp, tr[t].inv);
    tr[t].cov = tr[t].swp = tr[t].inv = 0;
}

stack<int> sta;
void access(int t,int k) {
    while (t != k) sta.push(t), t = fa[t];
    while (!sta.empty()) push_down(sta.top()), sta.pop();
}

void splay(int t,int &k) {
    access(t,k);
    while (t != k) {
        int x = fa[t] , y = fa[x];
        if (x != k) {
            if ((s[y][0] == x) ^ (s[x][0] == t))
                rotate(t,k);
            else
                rotate(x,k);
        }
        rotate(t,k);
    }
}

void build(int l,int r,int f,int &t) {
    if (!t) t = ++cnt;
    int mid = (l + r) >> 1;
    fa[t] = f; d[mid] = t;
    tr[t].a = a[mid];
//  update(t);
//  if (l == r) return ;
    if (l <= mid-1) build(l,mid-1,t,s[t][0]);
    if (mid+1 <= r) build(mid+1,r,t,s[t][1]);
    update(t);
}

void init() {
    n = rd(), m = rd();
    scanf("%s",st+1);
    for (int _=1;_<=n;_++) a[_] = st[_]=='(' ? 1 : -1;
}

int kth(int k,int t) {  
    push_down(t);  
    int tmp = L.siz + 1;  
    if (k == tmp) return t;  
    return tmp > k ? kth(k,s[t][0]) : kth(k-tmp,s[t][1]);  
}  

int get(int l,int r) {
    int g;
    g = kth(r+2,rt);
    splay(g,rt);

    g = kth(l,rt);
    splay(g,s[rt][0]);
    return s[ s[rt][0] ][1];
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
    #endif
    init();
    build(0,n+1,0,rt);
    while (m--) {
        char cmd[10]; scanf("%s",cmd+1);
        int l = rd(), r = rd(), g = get(l,r);
        if (cmd[1] == 'R') {
            char ch[5]; scanf("%s",ch+1);
            color(g, ch[1]=='('?1:-1, 0, 0);
        }  
        cmd[1] == 'S' ? color(g, 0, 1, 0) :0;
        cmd[1] == 'I' ? color(g, 0, 0, 1) :0;
        cmd[1] == 'Q' ? printf("%d\n",tr[g].ans[0].x + tr[g].ans[0].y/2) :0;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值