Codeforces 889F Letters Removing(二分 + 线段树 || 树状数组)

Posted Schenker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 889F Letters Removing(二分 + 线段树 || 树状数组)相关的知识,希望对你有一定的参考价值。

Letters Removing

题意:给你一个长度为n的字符串,然后进行m次删除操作,每次删除区间[l,r]内的某个字符,删除后并且将字符串往前补位,求删除完之后的字符串。

题解:

 

技术分享图片
  1 #include<set>
  2 #include<iostream>
  3 #include<string>
  4 using namespace std;
  5 #define lson l,m,rt<<1
  6 #define rson m+1,r,rt<<1|1
  7 const int N = 2e5+10;
  8 int n, m;
  9 int tree[N<<2];
 10 string str, tmp;
 11 set<int> G[80];
 12 void PushUp(int rt)
 13 {
 14     tree[rt] = tree[rt<<1|1] + tree[rt<<1];
 15 }
 16 void Revise(int L, int l, int r, int rt)
 17 {
 18     if(l == r)
 19     {
 20         tree[rt]++;
 21         return ;
 22     }
 23     int m = l+r >> 1;
 24     if(L <= m) Revise(L,lson);
 25     else Revise(L,rson);
 26     PushUp(rt);
 27 }
 28 int Query(int L, int R, int l, int r, int rt)
 29 {
 30     if(L <= l && r <= R)
 31         return tree[rt];
 32     int m = l+r >> 1;
 33     int ret = 0;
 34     if(L <=m) ret += Query(L,R,lson);
 35     if(m < R) ret+= Query(L,R,rson);
 36     return ret;
 37 }
 38 int mian()
 39 {
 40     ios::sync_with_stdio(false);
 41     cin.tie(0);
 42     cout.tie(0);
 43     cin >> n >> m;
 44     cin >> str;
 45     set<int>::iterator it;
 46     str = "#"+str;//将字符串往右整体移动一位
 47     for(int i = 1; i <= n; i++)
 48         G[str[i]-0].insert(i);//将对应的位置分别存到对应的set
 49     int l, r;
 50     while(m--)
 51     {
 52         cin >> l >> r >> tmp;
 53         bool flag = (l==r);//判断 l == r是否成立 如果成立可以少一次二分
 54         if(l + tree[1] > n) l = n+1;//如果区间左端点大于有效长度
 55         else                        //那么就表示不用进行删除操作了
 56         {
 57            int ll = l, rr = n;
 58            while(ll <= rr)
 59            {
 60                 int mm = ll + rr >> 1;
 61                 int num = Query(1,mm,1,n,1);
 62                 if(mm == num + l && str[mm] != .)
 63                 {
 64                     l = mm;
 65                     break;
 66                 }
 67                 else if(mm < num+l) ll = mm+1;
 68                 else rr = mm-1 ;
 69            }
 70         }
 71         if(flag) r = l;
 72         else
 73         {
 74             if(r + tree[1] > n) r = n;
 75             else
 76             {
 77                 int ll = r, rr = n;
 78                 while(ll <= rr)
 79                 {
 80                     int mm = ll + rr >> 1;
 81                     int num = Query(1,mm,1,n,1);
 82                     if(mm == num + r && str[mm] != .)
 83                     {
 84                         r = mm;
 85                         break;
 86                     }
 87                     else if(mm < num+r) ll = mm+1;
 88                     else rr = mm-1 ;
 89                 }
 90             }
 91 
 92         }
 93         if(l == n+1) continue;
 94         else
 95         {
 96             int pos =(int)tmp[0] - 0;
 97             it = G[pos].begin();
 98             while(it != G[pos].end())
 99             {
100                 int index = *it;
101                 if(index >= l && index <= r && str[index] != .)
102                 {
103                     Revise(index,1,n,1);
104                     str[index] = .;
105                 }
106                 if(index > r) break;
107                 it++;
108             }
109         }
110     }
111     for(int i = 1; i <= n; i++)
112     {
113         if(str[i] != .)
114             cout << str[i];
115     }
116     cout << endl;
117     return 0;
118 }
View Code

 

以上是关于Codeforces 889F Letters Removing(二分 + 线段树 || 树状数组)的主要内容,如果未能解决你的问题,请参考以下文章

Letters[Codeforces-43B]

CodeForces - 253E Table with Letters - 2

Codeforces 708A Letters Cyclic Shift

codeforces 1187 B Letters Shop

CodeForces 709C Letters Cyclic Shift

Codeforces Problem 708A Letters Cyclic Shift