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,每次可以交换两个相邻的元素,执行最小次数的交换移动 ...
随机推荐
- Nginx配置安装(Mac)
我用到的安装工具是:homebrew 真的很方便! 步骤1: 打开终端,输入 brew info nginx结果:我们可以看到,nginx在本地还未安装(Not installed),nginx的来源 ...
- MemCached的工具类。获取cached中的所有key
package com.ibs.auth.controller; import java.io.UnsupportedEncodingException; import java.util.Date; ...
- Python之assert断言语句
关键字assert构成断言语句,主要是可以在我们书写一个新的程序时,可以使用它帮我们锁定bug范围. 表达式: assert 表达式 ‘窗口提示的信息’ 括号中的项目为选填项目,选填项目将会在表达式的 ...
- 详解 git 忽略文件 删除远端仓库的文件
要解决的问题 忽略指定类型的文件 或 某个指定文件(夹) 将已经push到github的文件删除, 但本地的文件不删除 (写忽略规则之前就把这个文件夹push了 T_T ) 将想要忽略掉的文件的相关记 ...
- Java匹马行天下之J2EE框架开发——Spring—>Spring框架知多少
————也许我注定成不了一个伟大的人,但是至少我可以做一个很棒的自己.我想我现在应该做的不是瞻前顾后,而是活在当下,正确认知自己,做好自己现在的工作,努力提升自己的能力,踏踏实实地做一个程序员 一.思 ...
- dotnetcore 与 hbase 之一——hbase 环境准备
转载请注明出处www.cnblogs.com/hsxian! 总述 这是一系列针对 .net core (c#) 读取 hbase 的教程.本人苦于找不到 c#的原生 hbase 客户端,多番寻觅之下 ...
- Spring 集成Kafka(完整版)
前面的文章我们已经完成了Kafka基于Zookeeper的集群的搭建了.Kafka集群搭建请点我.记过几天的研究已经实现Spring的集成了.本文重点 jar包准备 集成是基于spring-integ ...
- XML学习(二)
1.上期回忆 XML基础 1)XML的作用 1.1 作为软件配置文件 1.2 作为小型的"数据库" 2)XML语法(由w3c组织规定的) 标签: 标签名不能以数字开头,中间不能有空 ...
- 自己动手实现MQTT协议
写在前面 前段时间弄IoT相关的东西,系统学习了一下 MQTT 协议,在此分享出来. 本文先是对 MQTT 协议做了简单的介绍:接着是对 MQTT协议的内容做了较为全面的解读:最后使用 Python ...
- CZGL.Auth: ASP.NET Core Jwt角色授权快速配置库
CZGL.Auth CZGL.Auth 是一个基于 Jwt 实现的快速角色授权库,ASP.Net Core 的 Identity 默认的授权是 Cookie.而 Jwt 授权只提供了基础实现和接口,需 ...