codeforces 558 E A Simple Task

题目大意就是给一个字符串,然后多个操作。每次操作能够把每一段区间的字符进行升序或者降序排序,问终于的字符串是如何的。

做法的话就是用线段树维护区间和

  一開始仅仅考虑字符串中字符‘a‘的情况。如果操作区间[L,R]中有x个‘a‘,那么一次操作后,这x个‘a‘要么去最左(升序)。要么去最右(降序),我们能够建立一颗线段树来维护这种操作,字符‘a‘出现的位置值为1,否则为0,那么q次操作后,最后值为1的地方填的就是‘a‘了。

  然后,在考虑字符‘a‘和‘b‘的情况,操作的情况和上面类似,字符‘a‘和‘b‘出现的位置值为1。否则为0,q次操作后,假设一个位置的值为1。而且该位置没有填写‘a‘。那么这个位置就填写‘b‘。

接下来的情况以此类推,考虑abc。abcd,......,abcd...z。

时间复杂度O(26*(n+q)logn)。

#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
struct Tree
{
	int l,r,sum;
}tree[int(4e5)];
void create(int l,int r,int k)
{
	tree[k].l=l;
	tree[k].r=r;
	tree[k].sum=0;
	if(l==r)
		return;
	int m=l+r>>1;
	create(l,m,k<<1);
	create(m+1,r,k<<1|1);
}
void lazy(int k)
{
	if(tree[k].l!=tree[k].r&&tree[k].sum!=tree[k<<1].sum+tree[k<<1|1].sum)
	{
		if(tree[k].sum==0)
			tree[k<<1].sum=tree[k<<1|1].sum=0;
		else
		{
			tree[k<<1].sum=tree[k<<1].r-tree[k<<1].l+1;
			tree[k<<1|1].sum=tree[k<<1|1].r-tree[k<<1|1].l+1;
		}
	}
}
void update(int l,int r,bool flag,int k)
{
	lazy(k);
	if(l==tree[k].l&&r==tree[k].r)
	{
		tree[k].sum=flag?r-l+1:0;
		return;
	}
	int m=tree[k].l+tree[k].r>>1;
	if(r<=m)
		update(l,r,flag,k<<1);
	else if(l>m)
		update(l,r,flag,k<<1|1);
	else
	{
		update(l,m,flag,k<<1);
		update(m+1,r,flag,k<<1|1);
	}
	tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
int seek(int l,int r,int k)
{
	lazy(k);
	if(l==tree[k].l&&r==tree[k].r)
		return tree[k].sum;
	int m=tree[k].l+tree[k].r>>1;
	if(r<=m)
		return seek(l,r,k<<1);
	if(l>m)
		return seek(l,r,k<<1|1);
	return seek(l,m,k<<1)+seek(m+1,r,k<<1|1);
}
void update(int l,int r,bool flag)
{
	int t=seek(l,r,1);
	if(flag)
	{
		if(l<=l+t-1)
			update(l,l+t-1,1,1);
		if(l+t<=r)
			update(l+t,r,0,1);
	}
	else
	{
		if(r-t+1<=r)
			update(r-t+1,r,1,1);
		if(l<=r-t)
			update(l,r-t,0,1);
	}
}
struct Box
{
	int l,r;
	bool flag;
}box[int(1e5)+10];
int ans[int(1e5)+10];
int main()
{
	int n,q;
	cin>>n>>q;
	create(1,n,1);
	string s;
	cin>>s;
	for(int i=0;i<q;i++)
		cin>>box[i].l>>box[i].r>>box[i].flag;
	for(int i=0;i<26;i++)
	{
		update(1,n,0,1);
		for(int j=0;j<n;j++)
			if(s[j]<=i+‘a‘)
				update(j+1,j+1,1,1);
		for(int j=0;j<q;j++)
			update(box[j].l,box[j].r,box[j].flag);
		for(int j=0;j<n;j++)
			if(ans[j]==0&&seek(j+1,j+1,1)==1)
				ans[j]=i+‘a‘;
	}
	for(int i=0;i<n;i++)
		putchar(ans[i]);
}

time limit per test

5 seconds

memory limit per test

512 megabytes

input

standard input

output

standard output

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 test(s)

input

10 5
abacdabcda
7 10 0
5 8 1
1 4 0
3 6 0
7 10 1

output

cbcaaaabdd

input

10 1
agjucbvdfk
1 10 1

output

abcdfgjkuv

Note

First sample test explanation:

时间: 2024-12-24 07:06:55

codeforces 558 E A Simple Task的相关文章

计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task

E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作,每次操作将(l,r)内的字符升序或降序排列,输出q次操作后的字符串. analyse: 基本思想是计数排序. 所谓计数排序,是对一个元素分布较集中的数字集群进行排序的算法,时间复杂度为O(n),但使用条件很苛刻.首先对n个数扫一遍,映射出每个数字出现的次数,然后再O(n)扫一遍处理出:对于数字ai,

Codeforces 558E A Simple Task (计数排序&amp;&amp;线段树优化)

题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memory limit per test512 megabytes inputstandard input outputstandard output This task is very simple. Given a string S of length n and q queries each quer

HUST 1341 A - A Simple Task(哈理工 亚洲区选拔赛练习赛)

A - A Simple Task Time Limit:1000MS    Memory Limit:131072KB    64bit IO Format:%lld & %llu SubmitStatusPracticeHUST 1341 Description As is known to all, lots of birds are living in HUST. A bird has s units of food on the first day, and eats k units

Codeforces 583 DIV2 Robot&#39;s Task 贪心

原题链接:http://codeforces.com/problemset/problem/583/B 题意: 就..要打开一个电脑,必须至少先打开其他若干电脑,每次转向有个花费,让你设计一个序列,使得总花费最小. 题解: 就傻傻的走就好..从左走到右,再走回来,更新序列和答案就好. 代码: #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #define MA

A Simple Task

A Simple Task 就像这道题的题目一样,真的是一个简单的题目,题意就是一句话:给一个数N求符合公式N = O * 2P的 O 和 P. 下面我们就一起看一下题吧. Description Given a positive integer n and the odd integer o and the nonnegative integer p such that n = o2^p. Example For n = 24, o = 3 and p = 3. Task Write a pr

HDU1339_A Simple Task【水题】

A Simple Task Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3987    Accepted Submission(s): 2181 Problem Description Given a positive integer n and the odd integer o and the nonnegative integ

Codeforces 467E Alex and Complicated Task(高效)

题目链接:Codeforces 467E Alex and Complicated Task 题目大意:给定一个长度为n序列,然后从中挑选尽量多的4元组(不能重叠). 解题思路:每次找的四元组的左端肯定是要尽量小的.所以用一个单调栈维护,如果新加入的数x在栈中出现过,那么就将两个数之间的数标记为在x.如果一个数的标记不为空,就意味着找到对应的四元组.有因为序列是从左遍历过去的,所以找到的一定是最优的. #include <cstdio> #include <cstring> #in

杭电 HDU ACM 1339 A Simple Task

A Simple Task Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4180    Accepted Submission(s): 2304 Problem Description Given a positive integer n and the odd integer o and the nonnegative integ

【题解】 CF11D A Simple Task

[题解] CF11D A Simple Task 传送门 \(n \le 20\) 考虑状态压缩\(dp\). 考虑状态,\(dp(i,j,O)\)表示从\(i\)到\(j\)经过点集\(O\)的路径有多少. \(dp(i,j,O \bigcup i)=\Sigma dp(i,p,O)\),\(j-p\)有一条边. 考虑内存,我们可以认定状态压缩串中\(lowbit(x)\)位是一条路的起点,这样我们直接省掉一维.空间限制卡进去了. 考虑答案怎么统计,就是\((\Sigma (dp(i,j,O)