Each month Blake gets the report containing main economic indicators of the company "Blake Technologies". There are n commodities produced by the company. For each of them there is exactly one integer in the final report, that denotes corresponding revenue. Before the report gets to Blake, it passes through the hands of m managers. Each of them may reorder the elements in some order. Namely, thei-th manager either sorts first ri numbers in non-descending or non-ascending order and then passes the report to the manager i + 1, or directly to Blake (if this manager has number i = m).
Employees of the "Blake Technologies" are preparing the report right now. You know the initial sequence ai of length n and the description of each manager, that is value ri and his favourite order. You are asked to speed up the process and determine how the final report will look like.
The first line of the input contains two integers n and m (1 ≤ n, m ≤ 200 000) — the number of commodities in the report and the number of managers, respectively.
The second line contains n integers ai (|ai| ≤ 109) — the initial report before it gets to the first manager.
Then follow m lines with the descriptions of the operations managers are going to perform. The i-th of these lines contains two integers tiand ri (, 1 ≤ ri ≤ n), meaning that the i-th manager sorts the first ri numbers either in the non-descending (if ti = 1) or non-ascending (if ti = 2) order.
Print n integers — the final report, which will be passed to Blake by manager number m.
3 1 1 2 3 2 2
2 1 3
4 2 1 2 4 3 2 3 1 2
2 4 1 3
In the first sample, the initial report looked like: 1 2 3. After the first manager the first two numbers were transposed: 2 1 3. The report got to Blake in this form.
In the second sample the original report was like this: 1 2 4 3. After the first manager the report changed to: 4 2 1 3. After the second manager the report changed to: 2 4 1 3. This report was handed over to Blake.
【题意】给了一个n个数的初始数组,然后给了m个操作,这些操作有两种:1 x,代表将前x个元素从小到大排序,2 x,代表将前x个元素从大到小排序,问你在m个操作完成之后,数组变为了什么。
【解题思路】这题其实是贪心思想的一个应用,首先找到最长的要操作的序列,然后找最长的之后第二长的,以此类推,找到所有可能会影响结果的有效操作,利用set进行插入删除,最后得到的数组必然就是操作完成后的数组。关键是如何找有效操作,现在开一个last数组,last[i]代表当前第i个操作是否需要操作,然后len[i]记录每一个操作序列的长度,那么last就可以根据len来更新了,这里要逆着更新,因为有效的操作肯定是在越后面发生的。
#include <bits/stdc++.h>
using namespace std;
multiset<int>s;
multiset<int>::iterator it;
const int nn = 200010;
int op[nn],ans[nn],len[nn],last[nn];
int main()
{
int n,m;
ios::sync_with_stdio();
cin.tie(0);
cin>>n>>m;
int maxlen=0;
for(int i=1; i<=n; i++)cin>>ans[i];
for(int i=1; i<=m; i++){
cin>>op[i]>>len[i];
maxlen = max(maxlen,len[i]);//维护最长的长度
}
for(int i=1; i<=maxlen; i++)s.insert(ans[i]);//将要改变的数丢进set
len[m+1]=0,last[m+1]=m+1;
for(int i=m; i>=1; i--)
{
if(len[i]>len[last[i+1]])//根据长度len更新last
{
last[i] = i;
}else{
last[i] = last[i+1];//不满住关系则用后一个last,更新这次的last.
}
}
int i=last[1];
int curlen = maxlen;//记录一下当前的最长长度,后面用得到
while(i<=m)
{
if(op[i]==1)//从大到小
{
int tmp = curlen;
int cnt = len[i]-len[last[i+1]];//上一个有效操作和这一个有效操作的差值就是需要操作的次数
while(cnt--)
{
auto it = s.end();
it--;
ans[tmp--] = *it;
s.erase(it);
}
curlen = tmp;
}
else//从小到大
{
int tmp = curlen;
int cnt = len[i]-len[last[i+1]];
while(cnt--)
{
auto it = s.begin();
ans[tmp--] = *it;
s.erase(it);
}
curlen = tmp;
}
i = last[i+1];
}
for(int i=1; i<=n; i++)cout<<ans[i]<<" ";
putchar('\n');
return 0;
}