zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:string(线段树)

    题目描述

    给定一个由小写字母组成的字符串$s$。

    有$m$次操作,每次操作给定$3$个参数$l,r,x$。

    如果$x=1$,将$s[l]~s[r]$升序排序;

    如果$x=0$,将$s[l]~s[r]$降序排序。

    你需要求出最终序列。


    输入格式

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


    输出格式

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


    样例

    样例输入

    5 2
    cabcd
    1 3 1
    3 5 0

    样例输出

    abdcc


    数据范围与提示

    对于$40\%$的数据,$n,mleqslant 1,000$。
    对于$100\%$的数据,$n,mleqslant 100,000$。


    题解

    看到这道题,我就想到了:[BZOJ4552]:[Tjoi2016&Heoi2016]排序(桶排序)

    然而,那道题我使用桶排序卡过的,时限还是$6,000ms$,所以我当场懵逼,线段树是肯定看出来了,但是不知道该怎么操作……

    打题一定要打正解挖~

    $40\%$算法:

    直接用$sort$搞就好了,重载一下运算符,我觉得我说的每一句都是废话……

    桶排一分也不能多拿(万恶的出题人)。

    时间复杂度:

      $Theta(m imes n)$(桶排序)。

      $Theta( m imes nlog n)$(快排)。

    期望得分:$40$分。

    $100\%$算法:

    因为这道题串中只有26个字母,所以就好说多了,用线段树维护区间内$a~z$的个数,每次修改拆成26个修改就行了。

    时间复杂度:$Theta(26 imes m imes log n)$。

    期望得分:$100$分。


    代码时刻

    $40\%$算法:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,l,r;
    bool x;
    int a[100001];
    char ch[100001];
    int t[50];
    int st,ed;
    void change1()
    {
    	register int maxn=0,minn=20020923,lft=l;
    	for(int i=l;i<=r;i++)
    	{
    		t[a[i]]++;
    		maxn=max(maxn,a[i]);
    		minn=min(minn,a[i]);
    	}
    	for(register int i=minn;i<=maxn;i++)
    		while(t[i])
    		{
    			a[lft++]=i;
    			t[i]--;
    		}
    }
    void change2()
    {
    	int maxn=0,minn=20020923,lft=l;
    	for(register int i=l;i<=r;i++)
    	{
    		t[a[i]]++;
    		maxn=max(maxn,a[i]);
    		minn=min(minn,a[i]);
    	}
    	for(register int i=maxn;i>=minn;i--)
    		while(t[i])
    		{
    			a[lft++]=i;
    			t[i]--;
    		}
    }
    
    int main()
    {
    	st=clock();
    	scanf("%d%d%s",&n,&m,ch+1);
    	for(register int i=1;i<=n;i++)
    		a[i]=ch[i]-'a'+1;
    	while(m--)
    	{
    		scanf("%d%d%d",&l,&r,&x);
    		if(x)change1();
    		else change2();
    	}
    	for(register int i=1;i<=n;i++)
    		printf("%c",(char)a[i]+'a'-1);
    	return 0;
    }
    

    $100\%$算法:

    #include<bits/stdc++.h>
    #define L(x) x<<1
    #define R(x) x<<1|1
    using namespace std;
    int n,m;
    char ch[100001];
    int tr[400001];
    int flag[30];
    void pushup(int x){if(tr[L(x)]==tr[R(x)])tr[x]=tr[L(x)];}
    void pushdown1(int x){if(tr[x])tr[L(x)]=tr[R(x)]=tr[x];}
    void pushdown2(int x){if(tr[x])tr[L(x)]=tr[R(x)]=tr[x];tr[x]=0;}
    void build(int x,int l,int r)
    {
    	if(l==r){tr[x]=ch[l]-'a'+1;return;}
    	int mid=(l+r)>>1;
    	build(L(x),l,mid);
    	build(R(x),mid+1,r);
    	pushup(x);
    }
    void ask(int x,int l,int r,int L,int R)
    {
    	if(r<L||R<l)return;
    	if(L<=l&&r<=R&&tr[x]){flag[tr[x]]+=r-l+1;return;}
    	int mid=(l+r)>>1;
    	pushdown1(x);
    	ask(L(x),l,mid,L,R);
    	ask(R(x),mid+1,r,L,R);
    }
    void change(int x,int l,int r,int L,int R,int v)
    {
    	if(r<L||R<l)return;
    	if((L<=l&&r<=R)||tr[x]==v){tr[x]=v;return;}
    	int mid=(l+r)>>1;
    	pushdown2(x);
    	change(L(x),l,mid,L,R,v);
    	change(R(x),mid+1,r,L,R,v);
    	pushup(x);
    }
    void print(int x,int l,int r)
    {
    	if(tr[x]){for(int i=l;i<=r;i++)printf("%c",(char)tr[x]+'a'-1);return;}
    	int mid=(l+r)>>1;
    	print(L(x),l,mid);
    	print(R(x),mid+1,r);
    }
    int main()
    {
    	scanf("%d%d%s",&n,&m,ch+1);
    	build(1,1,n);
    	while(m--)
    	{
    		int l,r,x;
    		scanf("%d%d%d",&l,&r,&x);
    		memset(flag,0,sizeof(flag));
    		ask(1,1,n,l,r);
    		if(x)for(int i=1;i<=26;i++){change(1,1,n,l,l+flag[i]-1,i);l+=flag[i];}
    		else for(int i=26;i>=1;i--){change(1,1,n,l,l+flag[i]-1,i);l+=flag[i];}
    	}
    	print(1,1,n);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    Effective Java 第三版——72. 赞成使用标准异常
    Effective Java 第三版——71. 避免不必要地使用检查异常
    Effective Java 第三版——70. 对可恢复条件使用检查异常,对编程错误使用运行时异常
    Effective Java 第三版——69. 仅在发生异常的条件下使用异常
    Effective Java 第三版——68. 遵守普遍接受的命名约定
    Effective Java 第三版——67. 明智谨慎地进行优化
    Effective Java 第三版——66. 明智谨慎地使用本地方法
    Effective Java 第三版——65. 接口优于反射
    Effective Java 第三版——64. 通过对象的接口引用对象
    Effective Java 第三版——63. 注意字符串连接的性能
  • 原文地址:https://www.cnblogs.com/wzc521/p/11285566.html
Copyright © 2011-2022 走看看