Topcoder SRM688 Div2 1000 ParenthesesDiv2Hard

来源:互联网 发布:sql中给表起别名 编辑:程序博客网 时间:2024/06/05 21:14

题目重述: 给出一个字符串s, 给定两个vector<int>L, R, 元素数目相同, 对于第i个元素,L[i]表示字符串s为L[i]的开始位置, R[i]值表示s在的终点位置, L[ i]和R[i]共同确定一个字符串s中的一个子串, 其中满足条件:在L[i]和R[i]确定的子串必须是正确的括号序列(定义题目有),并且这些子串之间不存在交叉的情况(问题简化了很多).要求对于给定的字符串s,对字符串的两个字符进行交换, 为使得序列能够满足上面的条件,返回最小的交换次数,如果无法满足,则返回-1.


思路: 先考虑哪些情况下返回-1的, 然后在找需要交换的序列.整个过程基本就是找"不合法的"左括号数目和"不合法的"右括号数目, 分别考虑每个子序列, 序列的一半即(R[i] - L[i] + 1 ) / 2为左括号和右括号的值, 同时考虑如果在当前括号状态不合法的时候则改变括号, 中间一直记录不合法的左括号和右括号的数值, 最后返回较大者.

int Left[60], Right[60];int ParenthesesDiv2Hard::minSwaps(string s, vector <int> L, vector <int> R){    int n = s.size(), m = L.size();    int l = 0, r = 0;    memset(Left, 0, sizeof(Left));    memset(Right, 0, sizeof(Right));    for(int i = 0; i < n; ++i){        if(s[i] == '('){            l ++;        }        else {            r ++;        }        Left[i + 1] = l;        Right[i + 1] = r;    }    int sum = 0, a = 0, b = 0;    for(int i = 0; i < m; ++i){        int ans = (R[i] - L[i] + 1);        if(ans % 2 != 0)return -1;        a += Left[R[i] + 1] - Left[L[i]];        b += Right[R[i] + 1] - Right[L[i]];        sum += ans / 2;    }    if(Right[n] < sum || Left[n] < sum)return -1;    l = 0, a = 0, b = 0;    int ln = 0;    for(int i = 0; i < m; ++i){        l = 0, ln = 0;        for(int j = L[i]; j <= R[i]; ++j){            int cv = (R[i] - L[i] + 1) / 2;            if(s[j] == '('){                if(ln >= cv){                    a ++;                    l --;                }                else {                    l ++;                    ln ++;                }            }            else {                if(l > 0){                    l--;                }                else {                    l++;                    ln++;                    b++;                }            }        }    }    return max(a, b);}


0 0
原创粉丝点击