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;
    }

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

  • 相关阅读:
    121. Best Time to Buy and Sell Stock
    70. Climbing Stairs
    647. Palindromic Substrings
    609. Find Duplicate File in System
    583. Delete Operation for Two Strings
    556 Next Greater Element III
    553. Optimal Division
    539. Minimum Time Difference
    537. Complex Number Multiplication
    227. Basic Calculator II
  • 原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758743.html
Copyright © 2011-2022 走看看