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 }
  • 相关阅读:
    【iCore4 双核心板_FPGA】例程八:乘法器实验——乘法器使用
    【iCore4 双核心板_ARM】例程十一:DMA实验——存储器到存储器的传输
    【iCore1S 双核心板_FPGA】例程八:触发器实验——触发器的使用
    【iCore4 双核心板_ARM】例程十:RTC实时时钟实验——显示时间和日期
    【iCore4 双核心板_ARM】例程九:ADC实验——电源监控
    WebBrowser的Cookie操作之流量刷新机
    网站受攻击的常用手段
    八爪鱼招标网的百度权重升为2了,独立IP也从0快速发展为1000
    网站添加数据出错,原来是MS SQL Server2008日志文件占据空间过大导致的
    当你的网站被疯狂攻击时你能做什么?
  • 原文地址:https://www.cnblogs.com/MingSD/p/8398053.html
Copyright © 2011-2022 走看看