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

需要注意的是,即使每次找到了两个端点,如果只是朴素总左到右遍历会TLE,所以可以给每个字符开一个set,每个set储存字符出现的位置。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#pragma warning ( disable : 4996 )
using namespace std; int Max( int a, int b ) { return a>b?a:b; }
int Min( int a, int b ) { return a>b?b:a; }
int lowbit( int x ) { return x&-x; } const int inf = 0x3f3f3f3f;
const int maxn = 2e5+; set<int> pos[];
set<int>::iterator it, it2;
char str[maxn];
int istr[maxn];
bool isdel[maxn]; int len, q; int getI( char c )
{
if( c >= 'a' && c <= 'z' ) return c-'a';
if( c >= 'A' && c <= 'Z' ) return c-'A'+;
if( c >= '' && c <= '' ) return c-''+;
} int sum( int x )
{
int ret = ;
while( x > )
{ ret += istr[x]; x -= lowbit(x); }
return ret;
} void add( int x, int d )
{
while( x <= len )
{ istr[x] += d; x += lowbit(x); }
} int find( int s )
{
int mid, lhs = , rhs = len;
int tmp;
while ( lhs <= rhs )
{
mid = (lhs+rhs)>>;
tmp = sum(mid);
if ( tmp >= s ) rhs = mid-;
else lhs = mid+;
}
return lhs;
} void change( int l, int r, char c )
{
int p = getI(c);
it = pos[p].lower_bound(l);
while ( it!=pos[p].end() && *it<=r )
{
isdel[(*it)] = true;
add((*it), -);
it2 = it; it++;
pos[p].erase(it2);
}
} int main()
{
cin >> len >> q;
scanf("%s", str+); for ( int i = ; i <= len; i++ )
{
add(i,);
int p = getI(str[i]);
pos[p].insert(i);
} int x, y;
char c;
for ( int i = ; i <= q; i++ )
{
scanf( "%d %d %c", &x, &y, &c );
x = find(x); y = find(y);
change( x, y, c );
} for( int i = ; i <= len; i++ )
if( !isdel[i] )
printf( "%c", str[i] ); printf("\n");
return ;
}

我们看到区间操作,自然就会想到线段树,但是数列下标是动态变换的,乍一看似乎线段树就没有用武之地了。实际仔细想想,线段树也可以动态统计从哪个区间开始操作,相比普通线段树只是在每次操作前要计算新的下标到哪了,实际上每个节点管辖的范围是始终不变的,变的只是范围内字符的个数size,每次操作前通过这个size找到对应的左端点和右端点就行了。

 //线段树
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#pragma warning ( disable : 4996 )
using namespace std; int Max( int a, int b ) { return a>b?a:b; }
int Min( int a, int b ) { return a>b?b:a; } const int inf = 0x3f3f3f3f;
const int maxn = 2e5+; struct tree {
int size, lhs, rhs;
int clu[];
}t[maxn<<];
char str[maxn]; int getI( char c )
{
if( c >= 'a' && c <= 'z' ) return c-'a';
if( c >= 'A' && c <= 'Z' ) return c-'A'+;
if( c >= '' && c <= '' ) return c-''+;
} char getC( int i )
{
if( i >= && i <= ) return 'a'+i;
if( i >= && i <= ) return 'A'+i-;
if( i >= && i <= ) return ''+i-;
} void pushUp( int index )
{
t[index].size = t[index<<].size + t[index<<|].size;
for ( int i = ; i < ; i++ )
t[index].clu[i] = t[index<<].clu[i] + t[index<<|].clu[i];
} void build( int l, int r, int index )
{
t[index].lhs = l; t[index].rhs = r;
if( l == r )
{ t[index].size = ; t[index].clu[getI(str[l-])] = ; return; }
int mid = (l+r)>>;
build(l, mid, index<<);
build(mid+, r, index<<|);
pushUp(index);
} int find( int index, int x )
{
int l = t[index].lhs, r = t[index].rhs;
if( l == r ) return l;
if( t[index<<].size >= x ) return find( index<<, x );
else return find( index<<|, x-t[index<<].size );
} void change( int index, int l, int r, int x )
{
int L = t[index].lhs, R = t[index].rhs;
if ( r < L || l > R ) return;
if ( !t[index].clu[x] ) return;
if ( L == R ) { t[index].size--; t[index].clu[x]--; return; }
change( index<<, l, r, x );
change( index<<|, l, r, x );
t[index].size = t[index<<].size + t[index<<|].size;
t[index].clu[x] = t[index<<].clu[x] + t[index<<|].clu[x];
} void print( int i )
{
int L=t[i].lhs,R=t[i].rhs;
if ( L==R )
{
for ( int j = ; j < ; j++ )
if ( t[i].clu[j] ) printf("%c",getC(j));
return;
}
print(i<<);
print(i<<|); } int main()
{
int len, q;
cin >> len >> q;
scanf("%s", str);
build(, len, ); int x, y;
char c;
for ( int i = ; i <= q; i++ )
{
scanf( "%d %d %c", &x, &y, &c );
int l = find( , x );
int r = find( , y );
change( , l, r, getI(c) );
}
print();
printf("\n");
return ;
}

Codeforces 899F Letters Removing 线段树/树状数组的更多相关文章

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

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

  2. 899F - Letters Removing

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

  3. Codeforces 889F Letters Removing(二分 + 线段树 || 树状数组)

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

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

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

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

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

  6. Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem E (Codeforces 831E) - 线段树 - 树状数组

    Vasily has a deck of cards consisting of n cards. There is an integer on each of the cards, this int ...

  7. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+ 树状数组或线段树

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  8. codeforces 540E 离散化技巧+线段树/树状数组求逆序对

    传送门:https://codeforces.com/contest/540/problem/E 题意: 有一段无限长的序列,有n次交换,每次将u位置的元素和v位置的元素交换,问n次交换后这个序列的逆 ...

  9. CodeForces 173E Camping Groups 离线线段树 树状数组

    Camping Groups 题目连接: http://codeforces.com/problemset/problem/173/E Description A club wants to take ...

随机推荐

  1. MongoDB特性及使用场景

    概述 MongoDB(Humongous Database),中文意思就是巨大无比的数据库,顾名思义,MongoDB就是为处理大数据而生,以解决海量数据的存储和高效查询使用为使命.MongoDB是一款 ...

  2. 论文阅读笔记---HetConv

    1 写在前边的话 HetConv性能:当使用HetConv取代标准卷积之后,FLOPs大概是之前的1/8到1/3,更重要的是精度几乎不变!!! 论文地址:https://arxiv.org/abs/1 ...

  3. Nodejs之路(四)—— MongoDB&MySQL

    一.MongoDB 1.1概述 MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案.MongoDB 是一个介于关系数据库和非 ...

  4. Linux 实用指令(5)--组管理和权限管理

    目录 组管理和权限管理 1 Linux组基本介绍 2 文件/目录 所有者 2.1 查看文件的所有者 2.2 修改文件所有者 3 组的创建 3.1 基本指令 3.2 应用实例 4 文件/目录 所在组 4 ...

  5. UMP系统功能 容灾

  6. SpringCloud之Fegin学习笔记

    以下部分内容来源于网络摘抄~ 1.作用 Feign 是一种声明式.模板化的 HTTP 客户端.在 Spring Cloud 中使用 Feign,可以做到使用 HTTP 请求访问远程服务,就像调用本地方 ...

  7. Entity Framework(code first)数据库初始化

    //1.修改模型,重设数据库 using System.Data.Entity; Database.SetInitializer<LisknoveDataContext>(newDropC ...

  8. Windbg 问题集锦记录

    问题1: 问: 0  Id: 15f4.e60 Suspend: 1 Teb: 7ffdf000 Unfrozen  # ChildEBP RetAddr  Args to Child         ...

  9. java基础之二维数组-杨辉三角

    首先呢你要知道什么是杨辉三角? 答:杨辉三角,是二项式系数在三角形中的一种几何排列. 简单的说一下就是两个未知数和的幂次方运算后的系数问题,比如(x+y)的平方=x的平方+2xy+y的平方,这样系数就 ...

  10. 【neo4j】neo4j Desktop1.1.9,windows 安装

    一.neo4j 介绍 Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌入式的.基于磁盘的.具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储 ...