zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    那些陌生的C++关键字
    从实现装饰者模式中思考C++指针和引用的选择
    单例模式(Singleton)
    命令模式(Command)
    抽象工厂模式(Abstract Factory)
    《Effective C++》读书摘要
    桥接模式(Bridge)
    适配器模式(Adapter)
    设计模式学习心得
    黑客常用WinAPI函数整理
  • 原文地址:https://www.cnblogs.com/bxd123/p/11185240.html
Copyright © 2011-2022 走看看