【FZU 1978】Repair the brackets (Splay)

来源:互联网 发布:怎么添加网络打印机xp 编辑:程序博客网 时间:2024/06/07 15:41

这道题的难点主要在于如果快速地求出一段括号序列最少改变多少个可以变成合法的。

看了题解报告才知道原来是这样的。

对于一段括号序列,设(为1,)为-1,则设从序列开始的和最小值为x,整段序列和为y

则(abs(y - x) + 1)/2 + (abs(x) + 1) / 2为答案

因为最小值则意味着前面有abs(x)个“)没有”(“与其匹配,因此至少需要将(abs(x) + 1) /2 个”)“变为(使得前半部分的括号暂时合法(暂时合法的意思是有可能后面会出现“)”与“(”匹配)。而y为该序列的和,则y + (-x)为前面一部分转换之后的括号之和,然后因为保证序列的长度为偶数,且经过第一步转化后不存在")"之前没有"("与之匹配的情况,因此直接将所有括号配对使得差值为0就可以了,因为答案需要再加上(abs(y - x) + 1)/2

再来看题意,因为题意中包含好几种操作,因此我们需要保证在操作之后还能维持信息的完整,因此需要记录从左边开始的最大值、最小值,从右边开始的最大值,最小值。

分别记录左右开始的值是因为当区间翻转的时候可以快速地得到所需信息,而最大最小值则是为了在inv操作的时候使得信息也能维护

具体看代码

#include<cstdio>#include<cstring>#include<algorithm>#define keytree (ch[ ch[root][1] ][0])using namespace std;const int SIZEN = 100005;struct SplayTree{int ch[SIZEN][2];int pre[SIZEN];int sz[SIZEN];int top,root;//**********************************inline void debug(){printf("root:%d\n",root);Travel(root);}inline void Travel(int x){if(ch[x][0]) Travel(ch[x][0]);printf("node:%2d lson:%2d rson:%2d pre:%2d sz:%2d val:%d sum:%d lx:%d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x],sum[x],lx[x][0]);if(ch[x][1]) Travel(ch[x][1]);}//***********debug***********************inline void Rotate(int x,int f){int y = pre[x],z = pre[y];pushdown(y);pushdown(x);ch[y][!f] = ch[x][f];pre[ ch[x][f] ] = y;pre[x] = z;if(z) ch[z][ ch[z][1] == y ] = x;ch[x][f] = y;pre[y] = x;pushup(y);pushup(x);}inline void Splay(int x,int goal){pushdown(x);while(pre[x] != goal){if(pre[ pre[x] ] == goal)Rotate(x,ch[ pre[x] ][0] == x);else{int y = pre[x],z = pre[y];int f = (ch[z][0] == y);if(ch[y][f] == x){Rotate(x,!f),Rotate(x,f);}else{Rotate(y,f),Rotate(x,f);}}}pushup(x);if(goal == 0) root = x;}inline void Rotateto(int k,int goal){int x = root;pushdown(x);while(sz[ ch[x][0] ] != k){if(sz[ ch[x][0] ] > k) x = ch[x][0];else{k -= sz[ ch[x][0] ] + 1;x = ch[x][1];}pushdown(x);}Splay(x,goal);}inline int idx(char c){if(c == '(') return 1;if(c == ')') return -1;}inline void pushup(int x){sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1;sum[x] = sum[ ch[x][0] ] + sum[ ch[x][1] ] + val[x];        lx[x][0] = min(lx[ ch[x][0] ][0],sum[ ch[x][0] ] + val[x] + lx[ ch[x][1] ][0]);        lx[x][1] = max(lx[ ch[x][0] ][1],sum[ ch[x][0] ] + val[x] + lx[ ch[x][1] ][1]);        rx[x][0] = min(rx[ ch[x][1] ][0],sum[ ch[x][1] ] + val[x] + rx[ ch[x][0] ][0]);        rx[x][1] = max(rx[ ch[x][1] ][1],sum[ ch[x][1] ] + val[x] + rx[ ch[x][0] ][1]);}inline void up_rev(int x){swap(lx[x][0],rx[x][0]);swap(lx[x][1],rx[x][1]);swap(ch[x][0],ch[x][1]);rev[x] ^= 1;}inline void up_set(int x,int c){Set[x] = c;val[x] = c;lx[x][0] = rx[x][0] = min(0,c * sz[x]);lx[x][1] = rx[x][1] = max(0,c * sz[x]);sum[x] = c * sz[x];inv[x] = 1;}inline void up_inv(int x){if(Set[x] != 0)Set[x] *= -1;elseinv[x] *= -1;val[x] *= -1;swap(lx[x][0],lx[x][1]);swap(rx[x][0],rx[x][1]);lx[x][0] *= -1;lx[x][1] *= -1;rx[x][0] *= -1;rx[x][1] *= -1;sum[x] *= -1;}inline void pushdown(int x){if(Set[x] != 0){if(ch[x][0]) up_set(ch[x][0],Set[x]);if(ch[x][1]) up_set(ch[x][1],Set[x]);Set[x] = 0;}if(inv[x] != 1){if(ch[x][0]) up_inv(ch[x][0]);if(ch[x][1]) up_inv(ch[x][1]);inv[x] = 1;}if(rev[x]){if(ch[x][0]) up_rev(ch[x][0]);if(ch[x][1]) up_rev(ch[x][1]);rev[x] = 0;}}int Newnode(char c){int x = ++top;ch[x][0] = ch[x][1] = pre[x] = 0;sz[x] = 1;sum[x] = val[x] = idx(c);lx[x][0] = rx[x][0] = min(0,idx(c));lx[x][1] = rx[x][1] = max(0,idx(c));Set[x] = rev[x] = 0;inv[x] = 1;return x;}inline void build(int &x,int l,int r,int f){if(l > r) return;int mid = (l + r) >> 1;x = Newnode(str[mid]);build(ch[x][0],l,mid - 1,x);build(ch[x][1],mid + 1,r,x);pre[x] = f;pushup(x);}inline void init(int n){ch[0][0] = ch[0][1] = pre[0] = 0;sz[0] = rev[0] = Set[0] = inv[0] = 0;lx[0][0] = lx[0][1] = 0;rx[0][0] = rx[0][1] = 0;val[0] = sum[0] = 0;top = root = 0;root = Newnode('(');ch[root][1] = Newnode(')');pre[ ch[root][1] ] = root;sz[root] = 2;scanf("%s",str);build(keytree,0,n - 1,ch[root][1]);pushup(ch[root][1]);pushup(root);}inline void Inv(){int l,r;scanf("%d%d",&l,&r);Rotateto(l - 1,0);Rotateto(r + 1,root);up_inv(keytree);pushup(ch[root][1]);pushup(root);}inline void Rev(){int l,r;scanf("%d%d",&l,&r);Rotateto(l - 1 ,0);Rotateto(r + 1 ,root);        up_rev(keytree);}inline void Replace(){int l,r;char c;scanf("%d%d %c",&l,&r,&c);Rotateto(l - 1,0);Rotateto(r + 1,root);up_set(keytree,idx(c));pushup(ch[root][1]);pushup(root);}inline void Query(){int l,r;scanf("%d%d",&l,&r);Rotateto(l - 1,0);Rotateto(r + 1,root);int x,y;x = lx[keytree][0];y = sum[keytree];y -= x;x = abs(x) + 1;y = abs(y) + 1;printf("%d\n",x / 2 + y / 2);}char str[SIZEN];int val[SIZEN];int sum[SIZEN];int inv[SIZEN],Set[SIZEN];int rev[SIZEN];int lx[SIZEN][2],rx[SIZEN][2];};SplayTree spt;void solve(){int n,m;char op[10];scanf("%d%d",&n,&m);spt.init(n);while(m--){scanf("%s",op);if(op[0] == 'I') spt.Inv();else if(op[0] == 'Q') spt.Query();else if(op[0] == 'R') spt.Replace();else if(op[0] == 'S') spt.Rev();}}int main(){int _,txt = 1;scanf("%d",&_);while(_--){printf("Case %d:\n",txt++);solve();}return 0;}/*18 4)))()()(Invert 6 7Swap 3 6Replace 5 7 (Query 4 7*/


0 0