zoukankan      html  css  js  c++  java
  • Codeforces 889F Letters Removing(二分 + 线段树 || 树状数组)

    Letters Removing

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

    题解:先开80个set 将每个字符对应的下标存入空间, 然后每次删除了一个字符之后就将字符串的相应位置改成一个不会产生干扰的字符(我这里使用的是'.')。 并且在线段树的相应位置标记一下。然后每次删除时候的左右区间就用2分区查找。

    找到位置pos 使得 [1,pos]的值等于 pos - l, 这样就可以找到相应的区间了。原因, [1,pos]的值代表着区间[1,pos]内被删除的元素个数是多少。 pos - 向左移动的数目([1,pos]) 就是在进行前面删除操作之后并往前补位的位置了。

     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 Find_pos(int pos)
    39 {
    40     int l = pos, r = n;
    41     while(l <= r)
    42     {
    43         int m = l+r >> 1;
    44         int num = Query(1,m,1,n,1);
    45         if(m == num + pos && str[m] != '.')
    46         {
    47             return m;
    48         }
    49         else if(m < num+ pos) l = m+1;
    50         else r = m - 1;
    51     }
    52 }
    53 int main()
    54 {
    55     ios::sync_with_stdio(false);
    56     cin.tie(0);
    57     cout.tie(0);
    58     cin >> n >> m;
    59     cin >> str;
    60     set<int>::iterator it;
    61     str = "#"+str;//将字符串往右整体移动一位
    62     for(int i = 1; i <= n; i++)
    63         G[str[i]-'0'].insert(i);//将对应的位置分别存到对应的set
    64     int l, r;
    65     while(m--)
    66     {
    67         cin >> l >> r >> tmp;
    68         if(l + tree[1] > n) continue;   //如果区间左端点大于有效长度
    69         if(l == r) l = r = Find_pos(l); //那么就表示不用进行删除操作了
    70         else {
    71                 l = Find_pos(l);
    72                 if(r + tree[1] > n) r = n;
    73                 else r = Find_pos(r);
    74              }
    75         int pos =(int)tmp[0] - '0';
    76         it = G[pos].begin();
    77         while(it != G[pos].end())
    78         {
    79             int index = *it;
    80             if(index >= l && index <= r)
    81             {
    82                 Revise(index,1,n,1);
    83                 str[index] = '.';
    84                 it = G[pos].erase(it);
    85             }
    86             else it++;
    87             if(index > r) break;
    88         }
    89     }
    90     for(int i = 1; i <= n; i++)
    91     {
    92         if(str[i] != '.')
    93             cout << str[i];
    94     }
    95     cout << endl;
    96     return 0;
    97 }

    树状数组代码:

     1 #include<set>
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 const int N = 2e5+10;
     6 int n, m;
     7 int tree[N];
     8 string str, tmp;
     9 set<int> G[80];
    10 int lowbit(int x)
    11 {
    12     return x&(-x);
    13 }
    14 void Add(int x)
    15 {
    16     while(x <= n)
    17     {
    18         tree[x]++;
    19         x += lowbit(x);
    20     }
    21 }
    22 int Query(int x)
    23 {
    24     int ret = 0;
    25     while(x > 0)
    26     {
    27         ret += tree[x];
    28         x -= lowbit(x);
    29     }
    30     return ret;
    31 }
    32 int Find_pos(int pos)
    33 {
    34     int l = pos, r = n;
    35     while(l <= r)
    36     {
    37         int m = l+r >> 1;
    38         int num = Query(m);
    39         if(m == num + pos && str[m] != '.')
    40         {
    41             return m;
    42         }
    43         else if(m < num+ pos) l = m+1;
    44         else r = m - 1;
    45     }
    46 }
    47 int main()
    48 {
    49     ios::sync_with_stdio(false);
    50     cin.tie(0);
    51     cout.tie(0);
    52     cin >> n >> m;
    53     cin >> str;
    54     set<int>::iterator it;
    55     str = "#"+str;//将字符串往右整体移动一位
    56     for(int i = 1; i <= n; i++)
    57         G[str[i]-'0'].insert(i);//将对应的位置分别存到对应的set
    58     int l, r;
    59     while(m--)
    60     {
    61         cin >> l >> r >> tmp;
    62         if(l + tree[1] > n) continue;  //如果区间左端点大于有效长度
    63         if(l == r) l = r = Find_pos(l);//那么就表示不用进行删除操作了
    64         else
    65         {
    66             l = Find_pos(l);
    67             if(r + tree[1] > n) r = n;
    68             else r = Find_pos(r);
    69         }
    70 
    71         int pos = tmp[0] - '0';
    72         it = G[pos].begin();
    73         while(it != G[pos].end())
    74         {
    75             int index = *it;
    76             if(index >= l && index <= r)
    77             {
    78                 Add(index);
    79                 str[index] = '.';
    80                 it = G[pos].erase(it);
    81             }
    82             else it++;
    83             if(index > r) break;
    84         }
    85     }
    86     for(int i = 1; i <= n; i++)
    87     {
    88         if(str[i] != '.')
    89             cout << str[i];
    90     }
    91     cout << endl;
    92     return 0;
    93 }
  • 相关阅读:
    转 du: 查看目录大小
    conductor v3 docker-compose 运行
    使用parquetjs 创建parquet 文件
    dremio 数据格式的一些说明
    集成minio sidekick & console 的测试
    hermes golang email 模版包
    gothic 类似gotrue 的服务
    cube.js 官方关于cube store 的一些实践说明
    dremio sql server 链接问题
    使用sbt-native-packager 构建通用的scala 软件包
  • 原文地址:https://www.cnblogs.com/MingSD/p/8398053.html
Copyright © 2011-2022 走看看