Letters Removing

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

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

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

 #include<set>
#include<iostream>
#include<string>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N = 2e5+;
int n, m;
int tree[N<<];
string str, tmp;
set<int> G[];
void PushUp(int rt)
{
tree[rt] = tree[rt<<|] + tree[rt<<];
}
void Revise(int L, int l, int r, int rt)
{
if(l == r)
{
tree[rt]++;
return ;
}
int m = l+r >> ;
if(L <= m) Revise(L,lson);
else Revise(L,rson);
PushUp(rt);
}
int Query(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R)
return tree[rt];
int m = l+r >> ;
int ret = ;
if(L <=m) ret += Query(L,R,lson);
if(m < R) ret+= Query(L,R,rson);
return ret;
}
int Find_pos(int pos)
{
int l = pos, r = n;
while(l <= r)
{
int m = l+r >> ;
int num = Query(,m,,n,);
if(m == num + pos && str[m] != '.')
{
return m;
}
else if(m < num+ pos) l = m+;
else r = m - ;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
cin >> n >> m;
cin >> str;
set<int>::iterator it;
str = "#"+str;//将字符串往右整体移动一位
for(int i = ; i <= n; i++)
G[str[i]-''].insert(i);//将对应的位置分别存到对应的set
int l, r;
while(m--)
{
cin >> l >> r >> tmp;
if(l + tree[] > n) continue; //如果区间左端点大于有效长度
if(l == r) l = r = Find_pos(l); //那么就表示不用进行删除操作了
else {
l = Find_pos(l);
if(r + tree[] > n) r = n;
else r = Find_pos(r);
}
int pos =(int)tmp[] - '';
it = G[pos].begin();
while(it != G[pos].end())
{
int index = *it;
if(index >= l && index <= r)
{
Revise(index,,n,);
str[index] = '.';
it = G[pos].erase(it);
}
else it++;
if(index > r) break;
}
}
for(int i = ; i <= n; i++)
{
if(str[i] != '.')
cout << str[i];
}
cout << endl;
return ;
}

树状数组代码:

 #include<set>
#include<iostream>
#include<string>
using namespace std;
const int N = 2e5+;
int n, m;
int tree[N];
string str, tmp;
set<int> G[];
int lowbit(int x)
{
return x&(-x);
}
void Add(int x)
{
while(x <= n)
{
tree[x]++;
x += lowbit(x);
}
}
int Query(int x)
{
int ret = ;
while(x > )
{
ret += tree[x];
x -= lowbit(x);
}
return ret;
}
int Find_pos(int pos)
{
int l = pos, r = n;
while(l <= r)
{
int m = l+r >> ;
int num = Query(m);
if(m == num + pos && str[m] != '.')
{
return m;
}
else if(m < num+ pos) l = m+;
else r = m - ;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
cin >> n >> m;
cin >> str;
set<int>::iterator it;
str = "#"+str;//将字符串往右整体移动一位
for(int i = ; i <= n; i++)
G[str[i]-''].insert(i);//将对应的位置分别存到对应的set
int l, r;
while(m--)
{
cin >> l >> r >> tmp;
if(l + tree[] > n) continue; //如果区间左端点大于有效长度
if(l == r) l = r = Find_pos(l);//那么就表示不用进行删除操作了
else
{
l = Find_pos(l);
if(r + tree[] > n) r = n;
else r = Find_pos(r);
} int pos = tmp[] - '';
it = G[pos].begin();
while(it != G[pos].end())
{
int index = *it;
if(index >= l && index <= r)
{
Add(index);
str[index] = '.';
it = G[pos].erase(it);
}
else it++;
if(index > r) break;
}
}
for(int i = ; i <= n; i++)
{
if(str[i] != '.')
cout << str[i];
}
cout << endl;
return ;
}

Codeforces 889F Letters Removing(二分 + 线段树 || 树状数组)的更多相关文章

  1. Codeforces 899F Letters Removing 线段树/树状数组

    虽然每次给一个区间,但是可以看作在区间内进行数个点操作,同样数列下标是动态变化的,如果我们将每个字符出现看作1,被删除看作0,则通过统计前缀和就能轻松计算出两个端点的位置了!这正是经典的树状数组操作 ...

  2. Educational Codeforces Round 61 D 二分 + 线段树

    https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...

  3. codeforces 899F Letters Removing set+树状数组

    F. Letters Removing time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  4. CodeForces - 1087F:Rock-Paper-Scissors Champion(set&数状数组)

    n players are going to play a rock-paper-scissors tournament. As you probably know, in a one-on-one ...

  5. CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)

    The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...

  6. 899F - Letters Removing

    Codeforces 899F - Letters Removing 思路:考虑一下怎么找到输入的l和r在原来串中的位置,我们想到用前缀和来找,一开始所有位置都为1,删掉后为0,那么前缀和为l的位置就 ...

  7. Codeforces 899 F. Letters Removing (二分、树状数组)

    题目链接:Letters Removing 题意: 给你一个长度为n的字符串,给出m次操作.每次操作给出一个l,r和一个字符c,要求删除字符串l到r之间所有的c. 题解: 看样例可以看出,这题最大的难 ...

  8. CodeForces992E 二分 + 树状数组(线段树)

    http://codeforces.com/problemset/problem/992/E 题意:给定一个序列 ai​ ,记其前缀和序列为 si​ ,有 q 个询问,每次单点修改,询问是否存在一个  ...

  9. codeforces 1269E K Integers (二分+树状数组)

    链接:https://codeforces.com/contest/1269/problem/E 题意:给一个序列P1,P2,P3,P4....Pi,每次可以交换两个相邻的元素,执行最小次数的交换移动 ...

随机推荐

  1. 【MySQL】

    org.springframework.dao.CannotAcquireLockException: PreparedStatementCallback; Lock wait timeout exc ...

  2. [Chat]实战:仿网易云课堂微信小程序开发核心技术剖析和经验分享

    本Chat以一个我参与开发并已上线运营近2年——类似网易云课堂的微信小程序项目,来进行微信小程序高级开发的学习. 本场Chat围绕项目开发核心技术分析,帮助你快速掌握在线视频.音频类小程序开发所需要的 ...

  3. 2、大型项目的接口自动化实践记录--接口测试简介及RequestsLibrary关键字简介

    1.接口测试简介 1)先简单介绍下接口测试,那么什么是接口测试呢? 百科的回答:接口测试是测试系统组件间接口的一种测试.接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点. 看起来有 ...

  4. Hadoop 系列(八)—— 基于 ZooKeeper 搭建 Hadoop 高可用集群

    一.高可用简介 Hadoop 高可用 (High Availability) 分为 HDFS 高可用和 YARN 高可用,两者的实现基本类似,但 HDFS NameNode 对数据存储及其一致性的要求 ...

  5. 几大排序算法的Java实现(原创)

    几大排序算法的Java实现 更新中... 注: 该类中附有随机生成[min, max)范围不重复整数的方法,如果各位看官对此方法有什么更好的建议,欢迎提出交流. 各个算法的思路都写在该类的注释中了,同 ...

  6. Selenium+java - Ajax浮动框处理

    Ajax浮动框 我们常遇到的某些网站首页输入框,点击后显示的浮动下拉热点,如下图: 实际案例 模拟场景如下: hao123首页搜索输入框,单击搜索框,点击浮动框中的哪吒票房破30亿,单击后选项的文字内 ...

  7. Spark1——介绍

    1.Spark是什么 Spark是一个用来实现快速而通用的集群计算的平台. 2.Spark是一个大一统的软件栈 Spark项目包含多个紧密集成的组件.首先Spark的核心是一个对由很多计算任务组成的. ...

  8. 最新 Flutter 团队工程师中文演讲 | Flutter 的性能测试和理论

    本视频为 Google Flutter 团队的软件工程师 Xiao Yu 在 2018 谷歌开发者大会做的演讲,演讲题目是<Flutter 的性能测试和理论>. 这个视频里将会通过近半个小 ...

  9. mpvue微信小程序项目踩坑记录

    1.mpvue入门教程, http://mpvue.com/mpvue/quickstart.html # . 先检查下 Node.js 是否安装成功 $ node -v v8.9.0 $ npm - ...

  10. 数据库炸了——是谁动了我的wait_timeout

    1.起因 隐约听到坐在我对面的测试说测试环境的接口有问题 他们一番商讨后,朝我这边反馈说,现在测试环境的接口报504 我条件反射的回了句那是接口超时,再多试几次(测试环境的性能比较差,尤其是数据库,经 ...