Codeforces 889F 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(二分 + 线段树 || 树状数组)的更多相关文章
- Codeforces 899F Letters Removing 线段树/树状数组
虽然每次给一个区间,但是可以看作在区间内进行数个点操作,同样数列下标是动态变化的,如果我们将每个字符出现看作1,被删除看作0,则通过统计前缀和就能轻松计算出两个端点的位置了!这正是经典的树状数组操作 ...
- Educational Codeforces Round 61 D 二分 + 线段树
https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...
- codeforces 899F Letters Removing set+树状数组
F. Letters Removing time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 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 ...
- CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)
The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...
- 899F - Letters Removing
Codeforces 899F - Letters Removing 思路:考虑一下怎么找到输入的l和r在原来串中的位置,我们想到用前缀和来找,一开始所有位置都为1,删掉后为0,那么前缀和为l的位置就 ...
- Codeforces 899 F. Letters Removing (二分、树状数组)
题目链接:Letters Removing 题意: 给你一个长度为n的字符串,给出m次操作.每次操作给出一个l,r和一个字符c,要求删除字符串l到r之间所有的c. 题解: 看样例可以看出,这题最大的难 ...
- CodeForces992E 二分 + 树状数组(线段树)
http://codeforces.com/problemset/problem/992/E 题意:给定一个序列 ai ,记其前缀和序列为 si ,有 q 个询问,每次单点修改,询问是否存在一个 ...
- codeforces 1269E K Integers (二分+树状数组)
链接:https://codeforces.com/contest/1269/problem/E 题意:给一个序列P1,P2,P3,P4....Pi,每次可以交换两个相邻的元素,执行最小次数的交换移动 ...
随机推荐
- Zabbix 中使用 Percona Monitoring Plugins 监控 MySQL
1.先安装agent客户端 tar zxvf zabbix-3.2.6.tar.gz cd zabbix-3.2.6 ./configure --prefix=/data/zabbix --enabl ...
- MySQL5.7运行CPU达百分之400处理方案
用户在使用 MySQL 实例时,会遇到 CPU 使用率过高甚至达到 100% 的情况.本文将介绍造成该状况的常见原因以及解决方法,并通过 CPU 使用率为 100% 的典型场景,来分析引起该状况的原因 ...
- 搭建nexus私服
一.安装 1.从网上下载nexus软件https://www.sonatype.com/download-oss-sonatype 下载Nexus Repository Manager OSS软件包 ...
- JavaScript数据结构——链表的实现与应用
链表用来存储有序的元素集合,与数组不同,链表中的元素并非保存在连续的存储空间内,每个元素由一个存储元素本身的节点和一个指向下一个元素的指针构成.当要移动或删除元素时,只需要修改相应元素上的指针就可以了 ...
- kubernetes API服务器的安全防护
12.1.了解认证机制 启动API服务器时,通过命令行选项可以开启认证插件. 12.1.1.用户和组 了解用户: 分为两种连接到api服务器的客户端: 1.真实的人 2.pod,使用一种称为Servi ...
- 算法与数据结构基础 - 字典树(Trie)
Trie基础 Trie字典树又叫前缀树(prefix tree),用以较快速地进行单词或前缀查询,Trie节点结构如下: //208. Implement Trie (Prefix Tree)clas ...
- mybatis批量更新策略
我们知道循环中操作db会导致连接数满,严重影响数据库性能.所以在对db进行DQL与DML时,根据业务逻辑尽量批量操作,这里我们介绍下使用mybatis批量更新mysql的两种方式. 方式一: < ...
- ZooKeeper系列(二)—— Zookeeper 单机环境和集群环境搭建
一.单机环境搭建 1.1 下载 下载对应版本 Zookeeper,这里我下载的版本 3.4.14.官方下载地址:https://archive.apache.org/dist/zookeeper/ # ...
- Javascript中,实现类与继承的方法和优缺点分析
Javascript是一种弱类型语言,不存在类的概念,但在js中可以模仿类似于JAVA中的类,实现类与继承 第一种方法:利用Javascript中的原型链 //首先定义一个父类 function An ...
- 建立apk定时自动打包系统第一篇——Ant多渠道打包并指定打包目录和打包日期
团队开发时,每天都需要输出一个apk包给其它部门的同事测试验证.打包几乎是每天必须完成的功课.如果用IDE来输出apk,那速度是非常慢的,如果还需要有不同渠道的apk包,那程序猿都要疯了.当然也有用 ...