题目要求每次都对前r个数进行升序或降序排序
我们发现 第一次对前三个数升序排序 如果第二次对前五个数排序 那第二次不管是升序还是降序都会覆盖第一次的排序 也就是说第一次的排序做了无用功
据此我们可以使用单调栈 来简化所给命令
注意 不可以对栈中每一个命令都彻底执行 比如
5 4
1 2 3 4 5
2 4
1 3
2 2
1 1
这样就有n^2*log(n)的复杂度
要充分利用已排序的部分 每执行一条命令 只需将部分元素逆序翻转即可 这样用两个变量 l r 就可实现 详见代码
#include <bits/stdc++.h>
using namespace std;
struct node
{
int t;
int p;
};
stack <int> ans;
node order[200010];
node stk[200010];
int num[200010];
int n,m,top,pos;
int cmp1(int u,int v)
{
return u<v;
}
int cmp2(int u,int v)
{
return u>v;
}
void init()
{
int i,j,maxx;
stk[0].t=0,stk[0].p=0;
maxx=0,top=0;
for(i=m;i>=1;i--)
{
if(order[i].t==stk[top].t)
{
if(order[i].p>stk[top].p)
{
stk[top]=order[i];
}
}
else
{
if(order[i].p>stk[top].p)
{
top++;
stk[top]=order[i];
}
}
}
return;
}
void calculate()
{
int i,t,l,r;
while(!ans.empty()) ans.pop();
l=1,r=n;
while(r>stk[top].p)
{
ans.push(num[r]);
r--;
}
if(stk[top].t==1) sort(num+l,num+r+1,cmp1);
else sort(num+l,num+r+1,cmp2);
top--;
while(top>=1)
{
if(l<=r)
{
while(r>l+stk[top].p-1)
{
ans.push(num[r]);
r--;
}
t=l,l=r,r=t;
}
else
{
while(r<l-stk[top].p+1)
{
ans.push(num[r]);
r++;
}
t=l,l=r,r=t;
}
top--;
}
if(l<=r)
{
while(l<=r)
{
ans.push(num[r]);
r--;
}
}
else
{
while(r<=l)
{
ans.push(num[r]);
r++;
}
}
while(!ans.empty())
{
printf("%d ",ans.top());
ans.pop();
}
printf("\n");
return;
}
int main()
{
int i,j,maxx,l,r;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
}
for(i=1;i<=m;i++)
{
scanf("%d%d",&order[i].t,&order[i].p);
}
init();
calculate();
}
return 0;
}