【hdu 5217】Brackets
Description
Miceren likes playing with brackets.
There are N brackets on his desk forming a sequence. In his spare time, he will do Q operations on this sequence, each operation is either of these two types:
1. Flip the X-th bracket, i.e. the X-th bracket will become ) if it is ( before, otherwise become ( .
2. In a given subsequence [L, R], query the K-th bracket position number after deleting all matched brackets. If the amount of brackets left is less than K, output -1. For example, if N = 10, L = 2, R = 9 and the sequence is ))(()))((). In the sub sequence [2, 9], the brackets sequence is )(()))((. After deleting all matched brackets, the sequence becomes ) )((. If K = 1, answer is 2. If K = 2, answer is 7. If K = 3, answer is 8. If K = 4, answer is 9. If K ≥ 5, answer is -1.
Miceren is good at playing brackets, instead of calculating them by himself.
As his friend, can you help him?
Input
The first line contains a single integer T, indicating the number of test cases.
Each test case begins with two integers N, Q, indicating the number of brackets in Miceren's desk and the number of queries.
Each of following Q lines describes an operation: if it is "1 X", it indicate the first type of operation. Otherwise it will be "2 L R K", indicating the second type of operation.
T is about 100.
1 ≤ N,Q ≤ 200000.
For each query, 1 ≤ X ≤ N and 1 ≤ L ≤ R ≤ N, 1 ≤ K ≤ N.
The ratio of test cases with N > 100000 is less than 10%.
Output
For each query operation, output the answer. If there is no K brackets left, output -1.
Sample Input
1
10 5
))(()))(()
2 2 9 2
2 2 9 3
2 2 9 5
1 3
2 2 9 5
Sample Output
7
8
-1
8
题意:给出一个括号序列和2种操作:1.翻转某一个括号;2.查询区间内完成括号匹配后第k个括号的原位置。($1\leq N,Q \leq 200000$)
分析:
易得,最后的序列一定形如 ')))(((' ,即左段皆为 ')',右段皆为 '(' 。我们可以建出一棵线段树,线段树上的每个节点对应区间内匹配后左段 '(' 的数量和右段 ')' 的数量。
区间合并与修改显然,主要问题在查询。至此我们可以通过查询区间[L,R]的信息快速得到第k个括号的类型。因为 '(' 在从右往左合并区间时单调不减, ')' 在从左往右合并区间时单调不减,所以可以在线段树上边跑边查询。详见代码。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define lc x<<1 5 #define rc x<<1|1 6 #define LL long long 7 using namespace std; 8 const int N=5e5+5; 9 int T,n,m,op,L,R,x; 10 int a[N],id[N],tl[N*4],tr[N*4]; 11 char ch[N]; 12 struct node{int t1,t0;}ans,now,tmp,t[N*4]; 13 int read() 14 { 15 int x=0,f=1;char c=getchar(); 16 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 17 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 18 return x*f; 19 } 20 node merge(node a,node b) 21 { 22 node c=(node){a.t1,b.t0}; 23 if(a.t0>b.t1)c.t0+=a.t0-b.t1; 24 else c.t1+=b.t1-a.t0; 25 return c; 26 } 27 void build(int x,int l,int r) 28 { 29 tl[x]=l;tr[x]=r; 30 if(l==r) 31 { 32 if(a[l])t[x]=(node){1,0}; 33 else t[x]=(node){0,1}; 34 id[l]=x;return; 35 } 36 int mid=(l+r)>>1; 37 build(lc,l,mid); 38 build(rc,mid+1,r); 39 t[x]=merge(t[lc],t[rc]); 40 } 41 void modify(int x,int l,int r,int p) 42 { 43 if(l==r) 44 { 45 swap(t[x].t0,t[x].t1); 46 return; 47 } 48 int mid=(l+r)>>1; 49 if(p<=mid)modify(lc,l,mid,p); 50 else modify(rc,mid+1,r,p); 51 t[x]=merge(t[lc],t[rc]); 52 } 53 void query(int x,int l,int r) 54 { 55 if(L<=l&&r<=R) 56 { 57 ans=merge(ans,t[x]); 58 return; 59 } 60 int mid=(l+r)>>1; 61 if(L<=mid)query(lc,l,mid); 62 if(R>mid)query(rc,mid+1,r); 63 } 64 int work0(int x,int l,int r,int goal) 65 { 66 if(l==r)return l; 67 int mid=(l+r)>>1; 68 tmp=now;now=merge(t[rc],now); 69 if(now.t0>=goal) 70 { 71 now=tmp; 72 return work0(rc,mid+1,r,goal); 73 } 74 return work0(lc,l,mid,goal); 75 } 76 int find0(int p,int goal) 77 { 78 int x=id[p]; 79 bool flag=false; 80 now=merge(t[x],now); 81 if(now.t0==goal)return p; 82 if(x&1)flag=true; 83 while(1) 84 { 85 x>>=1; 86 if(flag) 87 { 88 tmp=now;now=merge(t[lc],now); 89 if(now.t0>=goal){now=tmp;x=lc;break;} 90 } 91 if(x&1)flag=true; 92 else flag=false; 93 } 94 return work0(x,tl[x],tr[x],goal); 95 } 96 int work1(int x,int l,int r,int goal) 97 { 98 if(l==r)return l; 99 int mid=(l+r)>>1; 100 tmp=now;now=merge(now,t[lc]); 101 if(now.t1>=goal) 102 { 103 now=tmp; 104 return work1(lc,l,mid,goal); 105 } 106 return work1(rc,mid+1,r,goal); 107 } 108 int find1(int p,int goal) 109 { 110 int x=id[p]; 111 bool flag=true; 112 now=merge(now,t[x]); 113 if(now.t1==goal)return p; 114 if(x&1)flag=false; 115 while(1) 116 { 117 x>>=1; 118 if(flag) 119 { 120 tmp=now;now=merge(now,t[rc]); 121 if(now.t1>=goal){now=tmp;x=rc;break;} 122 } 123 if(x&1)flag=false; 124 else flag=true; 125 } 126 return work1(x,tl[x],tr[x],goal); 127 } 128 void work() 129 { 130 n=read();m=read(); 131 scanf("%s",ch+1); 132 for(int i=1;i<=n;i++) 133 if(ch[i]=='(')a[i]=0; 134 else a[i]=1; 135 build(1,1,n); 136 while(m--) 137 { 138 op=read(); 139 if(op==1) 140 { 141 x=read(); 142 modify(1,1,n,x); 143 continue; 144 } 145 L=read();R=read();x=read(); 146 ans.t0=ans.t1=0; 147 query(1,1,n); 148 if(ans.t0+ans.t1<x) 149 { 150 printf("-1\n"); 151 continue; 152 } 153 now.t0=now.t1=0; 154 if(x<=ans.t1)printf("%d\n",find1(L,x)); 155 else printf("%d\n",find0(R,ans.t0+ans.t1-x+1)); 156 } 157 } 158 int main() 159 { 160 T=read(); 161 while(T--)work(); 162 return 0; 163 }