Codeforces J. A Simple Task(多棵线段树)
题目描述:
Description
This task is very simple. Given a string S of length n and q queries each query is on the format i j k which means sort the substring consisting of the characters from i to j in non-decreasing order if k = 1 or in non-increasing order if k = 0.
Output the final string after applying the queries.
Input
The first line will contain two integers n, q (1 ≤ n ≤ 105, 0 ≤ q ≤ 50 000), the length of the string and the number of queries respectively.
Next line contains a string S itself. It contains only lowercase English letters.
Next q lines will contain three integers each i, j, k (1 ≤ i ≤ j ≤ n, ).
Output
Output one line, the string S after applying the queries.
Sample Input
10 5
abacdabcda
7 10 0
5 8 1
1 4 0
3 6 0
7 10 1
10 1
agjucbvdfk
1 10 1
Sample Output
cbcaaaabdd
abcdfgjkuv
思路:
题目的意思是,给定一个字符串,有q个询问,要把区间[l,r]的字符根据k的值升序(k=1),或降序(k=0)改变。
因为字母集有26个字母,就可以建立27棵线段树分别维护区间上每个字母出现的次数,一般地,第i棵线段树维护字母i-1+'a'的数目。
维护字母在区间上出现的次数有什么用?想想我们要做的事情,就是把区间[l,r]上的排一个序,字母集有限,想到计数排序,用一个27大小(0不存)的cnt数组,cnt[i]记录字母i出现的次数
如果k是1,则下标从1开始,如果对应那一项不为0,说明区间这个位置要被覆盖成i,就直接覆盖掉原来的线段树对应区间[l,r]上记录的字母i出现的次数,注意这里是直接覆盖,而不是累加,所以要修改线段树模板的区间和的upgrade函数的sum[a][r]+=改为sum[a][r]=,(a表示字母a对应的线段树)对应的懒标记也改为=。
一开始由于循环写的有点长(值代码长度),把计数的变量写叉了,有因为上面没有注意是最直接覆盖,一直出现out of bound错误,一开始还莫名其妙,搞了一个上午一直到晚上才知道写错了(╯‵□′)╯︵┻━┻,bug真好写,改是真难。
一开始写得麻烦了,比如把区间修改成字母a,然后我还在后面有把在这个区间上的,原来的对应的字母对应的线段树,一个位置一个位置的修改,然后提交,超时。。。
咋办嘞?原来只要在开始输入l,r那会统计每个字母在这个区间上出现次数后,紧接着立马删掉原来的数据(区间上的数据全置0),这么一改,好家伙,连样例都过不了了-_-||
找了半天,然后联想到这题的直接覆盖的不同寻常之处,也就是不同于区间和,才发现懒标记我标的有问题,没有懒标记我标0,懒标记为0(区间清零要用的)的还是0,那我在pushdown的时候怎么区分这两种情况呢?
咋办?标奇偶!神奇,覆盖的标记是1,清零的标记是2,没有标记的是0,这样就可以区分,那我咋使用呢?lz%2就行,1就是1,2就是0,可以正常使用了。
这题思路清晰,就是要注意细节,果然还是我太菜了。。
知识点:线段树的覆盖(自编题目)
代码:(开了氧气上瘾了)(注释依稀可见我超时的地方)
#include <iostream>
#include <cstring>
#include <memory.h>
#define max_n 100005
using namespace std;
char s[max_n];
int sum[][max_n<<];
int lz[][max_n<<];
int cnt[];
int n;
int q;
int k;
void pushup(int a,int r)
{
sum[a][r] = sum[a][r<<]+sum[a][r<<|];
}
void build(int a,int r,int lc,int rc)
{
if(lc==rc)
{
if(a==s[lc]-'a'+)
sum[a][r] = ;
lz[a][r] = ;
return;
}
int mid = (lc+rc)>>;
build(a,r<<,lc,mid);
build(a,r<<|,mid+,rc);
pushup(a,r);
}
void pushdown(int a,int r,int ln,int rn)
{
if(lz[a][r])
{
//cout << "r" << r << endl;
sum[a][r<<] = ln*(lz[a][r]%);//注意这里的改变
sum[a][r<<|] = rn*(lz[a][r]%);//还有这里
lz[a][r<<] = lz[a][r];
lz[a][r<<|] = lz[a][r];
lz[a][r] = ;
}
}
void upgrade(int a,int r,int L,int R,int lc,int rc,int val)
{
if(L<=lc&&rc<=R)
{
sum[a][r] = (rc-lc+)*(val%);//这里,这里!
lz[a][r] = val;//直接覆盖就是等于哦
return;
}
int mid = (lc+rc)>>;
pushdown(a,r,mid-lc+,rc-mid);
if(L<=mid) upgrade(a,r<<,L,R,lc,mid,val);
if(mid<R) upgrade(a,r<<|,L,R,mid+,rc,val);
pushup(a,r);
}
int query(int a,int r,int L,int R,int lc,int rc)
{
if(L<=lc&&rc<=R)
{
return sum[a][r];
}
int mid = (lc+rc)>>;
pushdown(a,r,mid-lc+,rc-mid);
int res = ;
if(L<=mid) res += query(a,r<<,L,R,lc,mid);
if(mid<R) res += query(a,r<<|,L,R,mid+,rc);
return res;
}
#pragma optimize(2)
int main()
{
cin >> n >> q;
for(int i = ;i<=n;i++)
{
cin >> s[i];
}
for(int i = ;i<=;i++)
{
build(i,,,n);
}
int l,r,k;
for(int i=;i<q;i++)
{
cin >> l >> r >> k;
for(int j = ;j<=;j++)
{
cnt[j] = query(j,,l,r,,n);
upgrade(j,,l,r,,n,);//直接清零
}
if(k==)
{
int lp = l;
for(int p = ; p<=; p++)
{
if(cnt[p])
{
char ch =p+'a'-;
//cout << ch << ":" << cnt[p] << endl;
upgrade(p,,lp,lp+cnt[p]-,,n,);
lp = lp+cnt[p];
/*for(int j = 0; j<cnt[p];j++)
{
upgrade(s[lp]-'a'+1,1,lp,lp,1,n,-1);
s[lp]=p+'a'-1;
lp++;
}*/
}
}
/*for(int i = 1; i<=n; i++)
{
cout << s[i];
}
cout << endl;*/
}
else
{
int lp = l;
for(int p = ; p>=; p--)
{
if(cnt[p])
{
char ch = p+'a'-;
//cout << ch << ":" << cnt[p] << endl;
upgrade(p,,lp,lp+cnt[p]-,,n,);
lp = lp+cnt[p];
/*for(int j = 0; j<cnt[p];j++)
{
upgrade(s[lp]-'a'+1,1,lp,lp,1,n,-1);
s[lp] = p+'a'-1;
lp++;
}*/ }
}
/*for(int i = 1; i<=n; i++)
{
cout << s[i];
}
cout << endl;*/
}
}
for(int i = ;i<=n;i++)
{
for(int j = ;j<;j++)
{
cnt[j] = query(j,,i,i,,n);
if(cnt[j])
{
char ch = j-+'a';
cout << ch;
}
}
}
cout << endl;
return ;
}
Codeforces J. A Simple Task(多棵线段树)的更多相关文章
- Codeforces 558E A Simple Task (计数排序&&线段树优化)
题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memor ...
- 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task
E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作, ...
- CodeForces 588E A Simple Task(线段树)
This task is very simple. Given a string S of length n and q queries each query is on the format i j ...
- Codeforces 588E. A Simple Task (线段树+计数排序思想)
题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...
- Codeforces 558E A Simple Task(计数排序+线段树优化)
http://codeforces.com/problemset/problem/558/E Examples input 1 abacdabcda output 1 cbcaaaabdd input ...
- codeforces 558E A Simple Task 线段树
题目链接 题意较为简单. 思路: 由于仅仅有26个字母,所以用26棵线段树维护就好了,比較easy. #include <iostream> #include <string> ...
- CodeForces - 960F Pathwalks —— 主席树(n棵线段树)
题目链接:https://vjudge.net/problem/CodeForces-960F You are given a directed graph with n nodes and m ed ...
- Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)
Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...
- codeforces 811E Vladik and Entertaining Flags(线段树+并查集)
codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...
随机推荐
- [LeetCode] 34. Search for a Range 搜索一个范围(Find First and Last Position of Element in Sorted Array)
原题目:Search for a Range, 现在题目改为: 34. Find First and Last Position of Element in Sorted Array Given an ...
- [LeetCode] 787. Cheapest Flights Within K Stops K次转机内的最便宜航班
There are n cities connected by m flights. Each fight starts from city u and arrives at v with a pri ...
- 使用Delphi开发linux应用
对于很多喜欢使用delphi做开发的人都希望delphi能够支持linux平台的开发,终于在delphi10.2版本中,delphi开始支持linux平台的开发了.在这里写一下Linux开发环境的配置 ...
- h5上拉加载更多
--------------------------------------------------------------------------例子1 <div class="bo ...
- Django实现博客项目
一.项目概述 项目运行环境 Python3.6+ Django 1.11 MySQL 5.7 其他插件(图片处理.分页.验证码....) 项目详细功能介绍 前台功能 项目首页展示 轮播图 博客推荐 最 ...
- 永久解决Sublime包管理package control 打开install package报错 There are no packages available for installation
很多用户在使用sumblime安装插件的时候,打开package control的install package会出现报错:There are no packages available for in ...
- Zabbix案例实践|Zabbix屏蔽告警
近期项目中,客户要求在凌晨00:00到02:00的CPU屏蔽虚拟化监控上ESXI的红色告警,红色告警是由于某台vmCPU利用率过高而产生的.做法如下:1. 找到红色告警的触发器,通过触发器找到监控项, ...
- 3.MVC基础-Code First 入门完整实例
1.添加一个EF的上下文类 EFDbContext public class EFDbContext:DbContext { public EFDbContext() : base("EF ...
- open_vPGPv
加密 // create an instance of the library PGPLib pgp = new PGPLib(); // Import the main company public ...
- 前端开发 Angular
https://www.angularjs.net.cn/tutorial/18.html