• CF558E A Simple Task


    Solution

    和之前有道省选题很像,同样是用线段树来实现排序操作。但这道题不同之处在于值域很小,以致于每个数的个数可以直接分别用线段树统计出来,这正是这道题的突破口。后面的就很好想了,每次对一个区间排序只需要统计所有字母的出现次数,然后按顺序区间覆盖,易知复杂度是 (O(nlog{n})) 的,带一个 26 的大常数(显然跑不满)。

    #include<stdio.h>
    #include<string.h>
    #define N 100007
    #define lid id<<1
    #define rid id<<1|1
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    struct Node{
        int s[30],cov,l,r,mid;
    }t[N<<2];
    
    char s[N];
    int n,m;
    
    void merge(Node &id,Node x,Node y){
        for(int i=1;i<=26;i++)
            id.s[i]=x.s[i]+y.s[i];
    }
    
    void build(int id,int lf,int rf){
        t[id].l=lf,t[id].r=rf;
        if(lf==rf) t[id].s[s[lf]-'a'+1]=1;
        else{
            t[id].mid=(lf+rf)>>1;
            build(lid,lf,t[id].mid);
            build(rid,t[id].mid+1,rf);
            merge(t[id],t[lid],t[rid]);
        }
    }
    
    void push(int id,int val){
        t[id].cov=val;
        for(int i=1;i<=26;i++) t[id].s[i]=0;
        t[id].s[val]=t[id].r-t[id].l+1;
    }
    
    void pushdown(int id){
        push(lid,t[id].cov);
        push(rid,t[id].cov);
        t[id].cov=0;
    }
    
    int l,r,val;
    Node query(int id){
        if(l<=t[id].l&&t[id].r<=r) return t[id];
        if(t[id].cov) pushdown(id);
        if(r<=t[id].mid) return query(lid);
        else if(l>t[id].mid) return query(rid);
        Node tmp;
        merge(tmp,query(lid),query(rid));
        return tmp;
    }
    
    void modify(int id){
        if(l<=t[id].l&&t[id].r<=r) push(id,val);
        else{
            if(t[id].cov) pushdown(id);
            if(l<=t[id].mid) modify(lid);
            if(r>t[id].mid) modify(rid);
            merge(t[id],t[lid],t[rid]);
        }
    }
    
    void print(){
        for(int i=1;i<=n;i++){
            l=r=i;
            Node ret=query(1);
            for(int i=1;i<=26;i++)
                if(ret.s[i]) putchar('a'+i-1);
        }
    //    putchar('
    ');
    }
    
    int main(){
        n=read(),m=read();
        scanf("%s",s+1);
        build(1,1,n);
        int op;
        for(int i=1;i<=m;i++){
            l=read(),r=read(),op=read();
            Node ret=query(1);
            if(op){
                int l_,r_=l-1;
                for(int i=1;i<=26;i++){
                    if(!ret.s[i]) continue;
                    l=r_+1,r=r_+ret.s[i],val=i,modify(1);
                    r_=r;
                }
            }else{
                int l_,r_=l-1;
                for(int i=26;i;i--){
                    if(!ret.s[i]) continue;
                    l=r_+1,r=r_+ret.s[i],val=i,modify(1);
                    r_=r;
                }
            }
        //    print();
        }
        print();
    }
    
  • 相关阅读:
    学习淘宝指数有感
    STL学习小结
    Java里泛型有什么作用
    android 内存泄漏分析技巧
    学道1.3
    严苛模式(StrictMode)
    年龄大了还能够学习编程吗
    ORACLE EXP命令
    数学之路-python计算实战(13)-机器视觉-图像增强
    《C语言编写 学生成绩管理系统》
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14190713.html
Copyright © 2020-2023  润新知