Report,又是一道思维题

Posted pl_er

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Report,又是一道思维题相关的知识,希望对你有一定的参考价值。

题目:

  

  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, the i-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.

Input

  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 ti and 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.

Output

  Print n integers — the final report, which will be passed to Blake by manager number m.

Examples:

Input
3 1
1 2 3
2 2
Output
2 1 3 
Input
4 2
1 2 4 3
2 3
1 2
Output
2 4 1 3 

题意:

  给你一个序列,对它进行操作1,2,1:把前i个数字非降序排列。2:把前i个数非升序排列。输出排列后的序列。

题目分析:

  首先,暴力肯定是妥妥的t掉的:每次都是nlogn,m次,显然不能解决这个问题,那我们能进行什么优化呢。

  考虑一下有什么无用的操作:举个例子:如果我对前5个数进行了某种排序,再对前10个数进行某种排序,前5个排序的操作就可以直接忽略掉了。这个应该很容易想到吧。于是,我们就可以维护一个类似单调队列的数据结构:如果某个操作比另一个操作晚出现,而且排的数比早的排的数要多,前面那一个操作就可以忽略掉了。最后,我们会得到这样一些操作:

  第i个操作为对前ai个数进行某种排序,且a1>a2>a3>...>an。

  这样的话,我们继续贪心:进行完第i个操作之后,我们就可以确定ai+1+1到ai的所有数了,于是,我们通过走一遍维护的“单调队列”,就可确定每一个数了。然后就是注意一下细节就好了。

代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int maxn=200000+10;
 5 int a[maxn];
 6 int b[maxn];
 7 int que[maxn];
 8 int c[maxn];
 9 int End;//最好大写首字母
10 int main(){
11     int n,m;
12     scanf("%d%d",&n,&m);
13     for(int i=1;i<=n;i++)
14         scanf("%d",&a[i]);
15     int js1,js2;
16     for(int i=1;i<=m;i++){
17         scanf("%d%d",&js1,&js2);
18         while(End&&que[End]<=js2)
19             End--;
20         End++;
21         que[End]=js2;
22         c[End]=js1;
23     }
24     sort(a+1,a+1+que[1]);
25     for(int i=que[1]+1;i<=n;i++)//把没有改变过的直接赋值
26         b[i]=a[i];
27     int left=1,right=que[1];
28     que[End+1]=0;//保证跑完后所有的数都被处理了
29     for(int i=1;i<=End;i++){
30         if(c[i]==2){
31             for(int j=left,j1=que[i];j<=left+que[i]-que[i+1]-1;j++,j1--)
32                 b[j1]=a[j];
33             left+=que[i]-que[i+1];
34         }
35         else{
36             for(int j=right,j1=que[i];j>=right+que[i+1]-que[i]-1;j--,j1--)
37                 b[j1]=a[j];
38             right-=que[i]-que[i+1];
39         }
40     }
41     for(int i=1;i<=n;i++)
42         printf("%d ",b[i]);
43     return 0;
44 }

 

 

  

 

以上是关于Report,又是一道思维题的主要内容,如果未能解决你的问题,请参考以下文章

HDU1757又是一道矩阵快速幂模板题

Aaronson,又是思维题

Aaronson 一道思维题

HDU - 5101 - Select(简单思维)

一道有意思的思维题 --- 排序枚举

又一道简单题&&Ladygod(两道思维水题)