zoukankan      html  css  js  c++  java
  • 【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个括号的原位置。($1leq 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
    ");
    151             continue;
    152         }
    153         now.t0=now.t1=0;
    154         if(x<=ans.t1)printf("%d
    ",find1(L,x));
    155         else printf("%d
    ",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 }
    View Code
  • 相关阅读:
    数据库注意事项
    SQL函数
    2019 SDN阅读作业(2)
    2019 SDN上机第五次作业
    2019 SDN上机第四次作业
    2019 SDN阅读作业
    2019 SDN上机第三次作业
    mysql使用记录
    2019 SDN上机第二次作业
    2019 SDN上机第一次作业
  • 原文地址:https://www.cnblogs.com/zsnuo/p/8897834.html
Copyright © 2011-2022 走看看