• [Contest on 2020.11.8] 排序


    ( ext{Descrption})

    题目描述

    ​ 给定一个仅由小写字母组成的字符串s。
    ​ 有m次操作,每次操作有3个参数L,R,opt。
    ​ 如果opt为1,那么将区间[L,R]内的字符按升序(即从'a'到'z')排列。
    ​ 如果opt为0,那么将区间[L,R]内的字符按降序(即从'z'到'a')排列。
    ​ 求m次操作后的字符串。

    输入格式

    ​ 第一行两个正整数 n 和 m,分别表示字符串的长度和操作次数。
    ​ 接下来一行一个长度为 n 的字符串。
    ​ 接下来 m 行每行 3 个正整数 L,R,opt_i,表示一个操作。

    输出格式

    输出一行一个长度为n的字符串,表示m次操作后的字符串。
    

    样例输入

    5 2
    cabcd
    1 3 1
    3 5 0
    

    样例输出

    abdcc
    

    数据规模与约定

    对于 40% 的数据, 1≤n≤1000 , 0≤m≤1000 。
    对于 100% 的数据, 1≤n≤10^5 , 0≤m≤10^5 , 0≤opt≤1 , 1≤L≤R≤n 。

    ( ext{Solution})

    感觉很神奇。

    其实关键就是这里的权值只有 (26) 种。

    我们可以从小到大枚举字母分界线 (ch),大于等于 (ch) 的字母赋为 (1),反之为 (0)。然后依次进行 (m) 次排序(以 (0,1) 为关键字),然后我们可以 (mathcal O(log n)) 地查询某个位置是否大于等于 (ch),如果是就先赋为 (ch),这样下一次当前的 (ch) 变成 (0),不会再被赋值,后面的字母也能被赋值。

    ( ext{Code})

    #include <cstdio>
    #define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
    #define print(x,y) write(x),putchar(y)
    
    int read() {
        int x=0,f=1; char s;
        while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
        return x*f;
    }
    
    void write(int x) {
        if(x<0) return (void)(putchar('-'),write(-x));
        if(x>9) write(x/10);
        putchar(x%10^48);
    }
    
    const int maxn=1e5+5;
    
    int n,m,L[maxn],R[maxn],op[maxn],t[maxn<<2];
    char s[maxn],ans[maxn];
    
    void pushDown(int o,int l,int r) {
    	int mid=l+r>>1;
    	if(t[o]==r-l+1) t[o<<1]=mid-l+1,t[o<<1|1]=r-mid;
    	else if(t[o]==0) t[o<<1]=t[o<<1|1]=0;
    }
    
    void modify(int o,int l,int r,int L,int R,int k) {
    	if(l>R||r<L) return;
    	if(l>=L&&r<=R) {t[o]=k*(r-l+1); return;}
    	int mid=l+r>>1;
    	pushDown(o,l,r);
    	modify(o<<1,l,mid,L,R,k); modify(o<<1|1,mid+1,r,L,R,k);
    	t[o]=t[o<<1]+t[o<<1|1];
    }
    
    int query(int o,int l,int r,int L,int R) {
    	if(l>R||r<L) return 0;
    	if(l>=L&&r<=R) return t[o];
    	int mid=l+r>>1;
    	pushDown(o,l,r);
    	return query(o<<1,l,mid,L,R)+query(o<<1|1,mid+1,r,L,R);
    }
    
    void work() {
    	rep(i,1,m) {
    		int cnt=query(1,1,n,L[i],R[i]);
    		if(cnt==R[i]-L[i]+1||cnt==0) continue;
    		if(op[i]) modify(1,1,n,L[i],R[i]-cnt,0),modify(1,1,n,R[i]-cnt+1,R[i],1);
    		else modify(1,1,n,L[i],L[i]+cnt-1,1),modify(1,1,n,L[i]+cnt,R[i],0);
    	}
    }
    
    int main() {
    	n=read(),m=read();
    	scanf("%s",s+1);
    	rep(i,1,m) L[i]=read(),R[i]=read(),op[i]=read();
    	for(char ch='a';ch<='z';++ch) {
    		rep(i,1,n) modify(1,1,n,i,i,s[i]>=ch);
    		work();
    		rep(i,1,n) if(query(1,1,n,i,i)) ans[i]=ch;
    	}
    	rep(i,1,n) putchar(ans[i]); puts("");
    	return 0;
    }
    
  • 相关阅读:
    jquery ajax参数详解
    压缩解压函数实现
    WCF 大数据量如何从服务端传到客户端
    [DllImport("kernel32.dll")]
    Oracle数据库使用基础和实例
    Js常用的动态效果
    Js使用正则实现表单验证
    Oracle数据库理论知识
    HTML5,CSS3,JavaScript基础知识与使用
    速读《人月神话》
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/13944611.html
Copyright © 2020-2023  润新知