CF558E A Simple Task 线段树

Posted bxd123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF558E A Simple Task 线段树相关的知识,希望对你有一定的参考价值。

  

题意翻译

题目大意: 给定一个长度不超过10^5的字符串(小写英文字母),和不超过50000个操作。

每个操作 L R K 表示给区间[L,R]的字符串排序,K=1为升序,K=0为降序。

最后输出最终的字符串。

 

 

给每个数字开一个线段树    如果该数字在pos位置  那么在该数字的线段树的pos 位置+1  (有一点类似权值线段树) 

因为一个点不是0就是1  (不可能有两个数字在一个点)开绝对标记即可

 

每次操作的时候  如果是递增的从小到大遍历数字的线段树即可  每次先找出区间个数  放在最左边即可

更改的代码非常秒  见代码

 

技术图片
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s)
#define ll long long
#define see(x) (cerr<<(#x)<<‘=‘<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
typedef pair<int,int>pii;
//////////////////////////////////
const int N=1e5+10;

int t[30][N<<2],col[30][N<<2],x,y,k,n,m,pos,cnt;
char s[N],ans[N];

void up(int pos,int num)

    t[num][pos]=t[num][pos<<1]+t[num][pos<<1|1];

void build(int l,int r,int pos)

    if(l==r)t[s[l]-a+1][pos]=1;return;
    int m=(l+r)>>1;build(lson);build(rson);rep(i,1,26)up(pos,i);

void down(int pos,int num,int m)

    if(col[num][pos]==-1)
    
        t[num][pos<<1]=t[num][pos<<1|1]=0;
        col[num][pos<<1]=col[num][pos<<1|1]=-1;
        col[num][pos]=0;
    
    else if(col[num][pos]>=1)
    
        t[num][pos<<1]=(m-(m>>1));
        t[num][pos<<1|1]=(m>>1);
        col[num][pos<<1]=col[num][pos<<1|1]=1;
        col[num][pos]=0;
    

int qsum(int L,int R,int num,int l,int r,int pos)

    int ans=0;if(L<=l&&r<=R)return t[num][pos];
    int m=(l+r)>>1;down(pos,num,r-l+1);
    if(L<=m)ans+=qsum(L,R,num,lson);if(R>m)ans+=qsum(L,R,num,rson);
    return ans;


void upsum(int L,int R,int num,int v,int l,int r,int pos)

    if(L<=l&&r<=R)  if(v) col[num][pos]=1;t[num][pos]=r-l+1; return ;  else  col[num][pos]=-1;t[num][pos]=0; return;     //注意一开始写成col[num][pos]++ wa 烂了 -1会加到0
    int m=(l+r)>>1;down(pos,num,r-l+1);
    if(L<=m)upsum(L,R,num,v,lson);if(R>m)upsum(L,R,num,v,rson);
    up(pos,num);

void seeall(int l,int r,int pos)

    if(l==r)
    
        rep(i,1,26)
        if(t[i][pos])ans[l]=i+a-1;  break; 
        return ;
    int m=(l+r)>>1;
    rep(i,1,26)down(pos,i,r-l+1);
    seeall(lson);seeall(rson);

int main()

    RII(n,m);
    RS(s+1);
    build(1,n,1);

    while(m--)
    
        RIII(x,y,k);pos=x;
        if(k)
        
            rep(i,1,26)
            
                cnt=qsum(x,y,i,1,n,1);
                if(!cnt)continue;
                upsum(x,y,i,0,1,n,1);
                upsum(pos,pos+cnt-1,i,1,1,n,1);pos=pos+cnt;
            
        
        else
        
            repp(i,26,1)
            
                cnt=qsum(x,y,i,1,n,1);
                if(!cnt)continue;
                upsum(x,y,i,0,1,n,1);
                upsum(pos,pos+cnt-1,i,1,1,n,1);pos=pos+cnt;
            
        
    
    seeall(1,n,1);
    printf("%s",ans+1);
    return 0;
View Code

以上是关于CF558E A Simple Task 线段树的主要内容,如果未能解决你的问题,请参考以下文章

CF558E A Simple Task

CF558E A Simple Task

CF558E A Simple Task

codeforces 558E A Simple Task 线段树

CF558E A Simple Task

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