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

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

原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758744.html