CF558E A Simple Task/string

题目描述:

给定一个由小写字母组成的字符串s。
有m次操作,每次操作给定3个参数l,r,x。
如果x = 1,将s[l] s[r]升序排序;
如果x = 0,将s[l] s[r]降序排序。
你需要求出最终序列。

输入格式:

第一行两个整数n,m。
第二行一个字符串s。
接下来m行每行三个整数x,l,r。

输出格式:

一行一个字符串表示答案。

输入样例:

5 2
cabcd
1 3 1
3 5 0

输出样例:

abdcc

数据范围:

对于100%的数据,n,m ≤ 100000。


思路

  • 数字代替字母,每一次操作取出区间所有数字再填入,线段树实现
  • 有关清零,每一次getcol就顺便将lazy标记清零,但不能在f数组加时清零,会错
  • 这篇题解似乎比较详细

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 100005
using namespace std;
struct fdfdfd{int l,r,val;}a[maxn<<2];
int n,m,f[30];
string st;
void pushup(int x){if(a[x<<1].val==a[x<<1|1].val) a[x].val=a[x<<1].val;}
void build(int x,int left,int right)
{
	a[x].l=left; a[x].r=right;
	if(left==right) {a[x].val=st[left-1]-'a'+1; return;}
	int mid=(left+right)>>1;
	build(x<<1,left,mid); build(x<<1|1,mid+1,right);
	pushup(x);
}
void getcol(int x,int left,int right)
{
	if(a[x].r<left||a[x].l>right) return;
	if(left<=a[x].l&&right>=a[x].r&&a[x].val) {f[a[x].val]+=a[x].r-a[x].l+1; return;}
	if(a[x].val) a[x<<1].val=a[x<<1|1].val=a[x].val;
	getcol(x<<1,left,right); getcol(x<<1|1,left,right);
}
void modify(int x,int left,int right,int d)
{
	if(a[x].r<left||a[x].l>right) return;
	if(left<=a[x].l&&right>=a[x].r) {a[x].val=d; return;}
	if(a[x].val) a[x<<1].val=a[x<<1|1].val=a[x].val,a[x].val=0;
	modify(x<<1,left,right,d); modify(x<<1|1,left,right,d);
	pushup(x);
}
void print(int x)
{
	if(a[x].val)
	{
		for(int i=a[x].l;i<=a[x].r;++i) printf("%c",a[x].val+'a'-1);
		return;
	}
	print(x<<1); print(x<<1|1);
}
int main()
{
    scanf("%d%d",&n,&m); cin>>st; build(1,1,n);
    for(int i=1,l,r,x;i<=m;++i)
    {
    	scanf("%d%d%d",&l,&r,&x);
    	memset(f,0,sizeof(f));
    	getcol(1,l,r);
    	if(x)
    	{
    		for(int j=1;j<=26;++j)
    			if(f[j]) modify(1,l,l+f[j]-1,j),l+=f[j];
    	}
    	else
    	{
    		for(int j=26;j>=1;--j)
    			if(f[j]) modify(1,l,l+f[j]-1,j),l+=f[j];
    	}
    }
    print(1);
    return 0;
}
原文地址:https://www.cnblogs.com/wuwendongxi/p/13667043.html