原题地址:http://codeforces.com/problemset/problem/631/C
题意
给定一个序列,先后依次进行m次操作,每一次都会把区间[1-r]内的数升序或者降序排列,求m次操作之后的序列
题解
很明显,对于某一段区间的数字,和对他们最后的操作有关
用Time[]数组记录对应位置操作的时间。
用opr[]数组记录对应位置操作的选择
首先,考虑两个操作,区间分别为[1,r1],[1,r2],时间为t1,t2,升降序分别为opr1,opr2;且t1>t2,opr1!=opr2;
如果r1>r2,那么2的操作的影响完全被覆盖,没有意义;
如果r1<r2,那么(r1,r2]这个区间受到opr2的影响,之后的区间则由opr1决定。
那么具体的对应关系是怎样的呢?
我们不妨假设r最大的区间要求升序,那么初始时整个数组升序,用双指针s,t分别指向0和r+1。
假如某个操作要求降序,那么受到该操作影响的部分应该是剩余序列的若干最小值,++s,对应地,如果某个操纵要求升序,则--t;
这道题s,t如何初始化,如何操作,值得讨论
#include<bits/stdc++.h> #define clr(x,y) memset((x),(y),sizeof(x)) using namespace std; typedef long long LL; const int maxn=2e5; int A[maxn+5]; int Time[maxn+5]; int opr[maxn+5]; int ans[maxn+5]; int s,t,p,d,start; void Copy(int x) { if (x==opr[start]) { for (int j=1;j<=d;++j) { --t; --p; ans[p]=A[t]; } } else { for (int j=1;j<=d;++j) { ++s; --p; ans[p]=A[s]; } } d=0; } int main(void) { #ifdef ex freopen ("../in.txt","r",stdin); //freopen ("../out.txt","w",stdout); #endif int n,m; scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) { scanf("%d",&A[i]); } clr(Time,0); clr(opr,0); int tt,tr; for (int i=1;i<=m;++i) { scanf("%d%d",&tr,&tt); Time[tt]=i; opr[tt]=tr; } for (int i=n;i>=1;--i) { if (Time[i]) { start=i; break; } ans[i]=A[i]; } if (opr[start]==1) sort(A+1,A+start+1); else sort(A+1,A+start+1,greater<int>() ); //ans[start]=A[start]; s=0; t=start+1; int now_time=0; int now_opr=3; d=0; p=start+1; Time[0]=m+1; for (int i=start;i>=0;--i) { if (Time[i]>now_time) { Copy(now_opr); now_opr=opr[i]; now_time=Time[i]; } ++d; } for (int i=1;i<=n;++i) printf("%d ",ans[i]); }