HDU 5217 Brackets 线段树

题目大意:

给出括号序列然后两种操作:

1.修改某个括号为另外一种

2.询问在区间[L, R]中的括号在忽略掉匹配好的括号之后第K个括号的位置, 即没有匹配的括号中第K个的位置


大致思路:

首先可以对于括号序列建立线段树, 线段树每个节点表示当前区间[L, R]中没有匹配的')'数量和'('数量, 这个是可以满足区间合并的

那么对于每次询问当没匹配的')'和‘(‘总数不够K时就是-1, 否则的话分治一下, 对于是‘)'的情况从左往右看, 对于是'('的情况从右往左看, 考虑第K个没匹配的括号在[L, R]二分之后的左边区间还是右边区间, 注意在递归向下的时候K会发生的变化即可, 建立线段树O(n), 每次修改复杂度O(logn), 每次询问复杂度O((logn)^2)


代码如下:

交了G++才过....布吉岛是不是因为有更好的解法...还是因为代码写搓了...

加了整数的读入优化的...


Result  :  Accepted     Memory  :  5912 KB     Time  :  7113 ms

/*
 * Author: Gatevin
 * Created Time:  2015/9/10 16:28:29
 * File Name: Sakura_Chiyo.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

#define maxn 200010
char in[maxn];
int n, Q;

inline int Max(int x, int y)
{
    if(x > y) return x;
    return y;
}

struct Segment_Tree
{
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
    struct State
    {
        int l, r;
        State(int _l, int _r)
        {
            l = _l, r = _r;
        }
        State(){};
    };
    State s[maxn << 2];
    void pushUp(int rt)
    {
        s[rt] = State(s[rt << 1].l + Max(0, s[rt << 1 | 1].l - s[rt << 1].r), 
                      s[rt << 1 | 1].r + Max(0, s[rt << 1].r - s[rt << 1 | 1].l));
    };
    void build(int l, int r, int rt)
    {
        if(l == r)
        {
            if(in[l] == ')')
                s[rt] = State(1, 0);
            else s[rt] = State(0, 1);
            return;
        }
        int mid = (l + r) >> 1;
        build(lson);
        build(rson);
        pushUp(rt);
    }
    void update(int l, int r, int rt, int pos)
    {
        if(l == r)
        {
            if(in[l] == '(') in[l] = ')';
            else in[l] = '(';
            if(in[l] == '(')
                s[rt] = State(0, 1);
            else s[rt] = State(1, 0);
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid) update(lson, pos);
        else update(rson, pos);
        pushUp(rt);
    }
    State query(int l, int r, int rt, int L, int R)
    {
        if(l >= L && r <= R)
            return s[rt];
        int mid = (l + r) >> 1;
        State sl, sr;
        bool fl = 0, fr = 0;
        if(mid >= L) sl = query(lson, L, R), fl = 1;
        if(mid + 1 <= R) sr = query(rson, L, R), fr = 1;
        if(!fl) return sr;
        if(!fr) return sl;
        return State(sl.l + Max(0, sr.l - sl.r),
                     sr.r + Max(0, sl.r - sr.l));
    }
    int find(int L, int R, int K, char c)
    {
        if(L == R) return L;
        int mid = (L + R) >> 1;
        if(c == ')')
        {
            State sl = query(1, n, 1, L, mid);
            if(sl.l >= K) return find(L, mid, K, c);
            else return find(mid + 1, R, K - sl.l + sl.r, c);
        }
        else
        {
            State sr = query(1, n, 1, mid + 1, R);
            if(sr.r >= K) return find(mid + 1, R, K, c);
            else return find(L, mid, K - sr.r + sr.l, c);
        }
    }
    void solve(int L, int R, int K)
    {
        State ret = query(1, n, 1, L, R);
        if(ret.l + ret.r < K)
        {
            printf("-1\n");
            return;
        }
        if(ret.l >= K)//说明这个括号是')'
            printf("%d\n", find(L, R, K, ')'));//[L, R]中从左往右第K个')'
        else printf("%d\n", find(L, R, ret.l + ret.r - K + 1, '('));//说明这个括号是从右往左第 ret.l + ret.r - K + 1个'('
    }
};

Segment_Tree st;

void Get(int &x)
{
    x = 0;
    char c;
    while(1)
    {
        c = getchar();
        if(c >= '0' && c <= '9') x = x*10 + c - '0';
        else break;
    }
}

int main()
{
    int T;
    //scanf("%d", &T);
    Get(T);
    while(T--)
    {
        //scanf("%d %d", &n, &Q);
        Get(n);
        Get(Q);
        gets(in + 1);
        st.build(1, n, 1);
        while(Q--)
        {
            int op;
            //scanf("%d", &op);
            Get(op);
            if(op == 1)
            {
                int pos;
                //scanf("%d", &pos);
                Get(pos);
                st.update(1, n, 1, pos);
            }
            else
            {
                int L, R, K;
                //scanf("%d %d %d", &L, &R, &K);
                Get(L); Get(R); Get(K);
                st.solve(L, R, K);
            }
        }
    }
    return 0;
}



你可能感兴趣的:(线段树,HDU,Brackets,5217)