• Codeforces Round #344 (Div. 2) C. Report


    Report

    题意:给长度为n的序列,操作次数为m;n and m (1 ≤ n, m ≤ 200 000) ,操作分为t r,当t = 1时表示将[1,r]序列按非递减排序,t = 2时表示将序列[1,r]按非递增排序;输出m次操作后的序列?

    思路:由于排序是前缀排序,那么前面的操作ti,ri;如果 ri <= rj;那么第i次操作直接被覆盖了。这样我们可以知道有用的排序操作ri是按照严格递减的;并且这时在ri 与r(i + 1)之间的数与后面的操作无关了~~(线性处理),这就直接说明了只需要排序一次,即对于[1,max(ri)]排序,之后直接用双指针在排好序的数组中找到对应的值填到结果数组中即可;

    #include<bits/stdc++.h>
    using namespace std;
    typedef __int64 ll;
    template<typename T>
    void read1(T &m)
    {
        T x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        m = x*f;
    }
    template<typename T>
    void read2(T &a,T &b){read1(a);read1(b);}
    template<typename T>
    void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
    const int N = 200200;
    int a[N],b[N],t[N],r[N],p[N],q[N];
    int main()
    {
        int n,m;
        read2(n,m);
        for(int i = 1;i <= n;i++)  read1(a[i]),b[i] = a[i];
        for(int i = 1;i <= m;i++)  read2(t[i],r[i]);
        int mx = 0, cnt = 0;
        for(int i = m;i >= 1; i--){//逆序增加mx;压缩出有用的排序即可;
            if(r[i] > mx)
                mx = r[i],p[++cnt] = r[i],q[cnt] = t[i];
        }
        p[0] = 0;//完全处理;
        sort(b + 1,b + mx + 1);//a最终排序的元素在b中找即可;
        int la = 1, ra = mx, lb = 1,rb = mx;
        for(int i = cnt;i > 0;i--){
            if(q[i] == 1)
                for(;ra > p[i - 1];ra--,rb--) a[ra] = b[rb];
            else
                for(;ra > p[i - 1];ra--,lb++) a[ra] = b[lb];
        }
        for(int i = 1;i <= n;i++)
            printf("%d ",a[i]);
        return 0;
    }
  • 相关阅读:
    ★★★
    ★★
    小狼程序员:工作遐想
    广联达BB了
    计算机网络简单理解
    做个合格的(优秀的)测试开发人员
    开发、测试、测试开发
    8.21
    C++ 选择题总结(回调函数 || 类方法(实例方法)|| )
    深拷贝实现笔记
  • 原文地址:https://www.cnblogs.com/hxer/p/5246171.html
Copyright © 2020-2023  润新知