zoukankan      html  css  js  c++  java
  • Codeforces 631C Report【其他】

    题意:

    给定序列,将前a个数进行逆序或正序排列,多次操作后,求最终得到的序列。

    分析:

    仔细分析可以想到j<i,且rj小于ri的操作是没有意义的,对于每个i把类似j的操作删去(这里可以用multiset或者直接模拟栈的操作),最后我们会获得一个严格下降的序列即ri>rj && i<j,并且相邻的t不相等。
    那么对于riri+1,对[0,ri)进行排序后,又对其子序列[0,ri+1)进行相反的排序,其实只有区间[ri+1,ri1]]内的数是按照ti规定的排序的,并且不会再改变。所以我们只需要根据ti获取[ri+1,ri1]]之间的值即可。
    那么如何获取呢?在头尾两头设两个指针,如果对应区间要求升序,则用大的数填,否则用小的数填上。

    代码:

    用multiset做(做题太少第一次用set的erase)

    #include <cstdio>
    #include<set>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int maxn = 200005;
    int a[maxn], b[maxn];
    typedef pair<int, int>p;
    #define fi first
    #define se second
    multiset<p>ms;
    int main (void)
    {
        int n, m;scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++){
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        int maxr = 0;
        int r, t;
        multiset<p>::iterator pos;
        multiset<p>::iterator rp;
        for(int i = 0; i < m; i++){
            scanf("%d%d", &t, &r);
            p tp = p(r, t);
            maxr = max(maxr, r);
            rp = ms.begin();
            while(rp ->first <= tp.first && rp!=ms.end())
                 ms.erase(rp++);
            ms.insert(tp);
        }
        sort(b, b + maxr);
        int u = maxr - 1, l = 0;
        pos = ms.end();
        pos--;
        int cnt = 0;
        while(cnt < ms.size()){
            int tmp = pos->se;
            cnt++;
            if(cnt == ms.size()){
                for(int j = (pos->fi) - 1; j >=0; j--){
                    if(tmp == 1) a[j] = b[u--];
                    else a[j] = b[l++];
                }
            }
            else{
                rp = pos--;
                for(int j = (rp->fi) - 1; j >= pos->fi; j--){
                    if(tmp == 1) a[j] = b[u--];
                    else a[j] = b[l++];
                }
           }
         }
        for(int i = 0; i < n; i++){
           printf("%d%c", a[i], i == n - 1?'
    ':' ' );
        }
        return 0;
    }

    模拟栈的操作

    #include <cstdio>
    #include<algorithm>
    using namespace std;//区间递减且t交叉
    const int maxn = 200005;
    int a[maxn], b[maxn], t[maxn], r[maxn];
    int main (void)
    {
        int n, m;scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++){
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        int s = 0;
        for(int i = 0; i < m; i++){
            scanf("%d%d", &t[i], &r[i]);
            while(s > 0 && r[i] >= r[s - 1]){
                s--;
            }
            t[s] = t[i], r[s] = r[i]; s++;
        }
       sort(b, b + r[0]);
       int l = r[0] - 1, u = 0;
        r[s] = 0;
       for(int i = 1; i < s + 1; i++){
        for(int j = r[i - 1] - 1; j >= r[i]; j--){
            if(t[i - 1] == 2) a[j] = b[u++];
            else a[j] = b[l--];
            }
       }
       //for(int i = 0; i < n; i++) printf("%d",b[i]);
       for(int i = 0; i < n; i++)
            printf("%d%c", a[i], i==n-1?'
    ':' ');
        return 0;
    }

    智商捉急。。。。比赛的时候就是想不到怎么保存有意义的操作, 就断定这题是一定是要用到自己没学过的数据结构。。真的要对自己自信呀~~思考思考!!

  • 相关阅读:
    JS动态计算rem
    Vue数据双向绑定原理
    NOI2019 退役记
    友情链接
    算法博客总结
    总结各类错误(always online)
    学习笔记:powerful number求积性函数前缀和
    LOJ#2409. 「THUPC 2017」小 L 的计算题 / Sum(生成函数)
    多项式简单操作
    LOJ #3103. 「JSOI2019」节日庆典
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758744.html
Copyright © 2011-2022 走看看