Codeforces Round #344 (Div. 2) 631 C. Report (单调栈)

C. Report
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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
inputCopy
3 1
1 2 3
2 2
outputCopy
2 1 3
inputCopy
4 2
1 2 4 3
2 3
1 2
outputCopy
2 4 1 3
Note
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类型是将1到r的进行不下降排序,2类型是将1到r进行不上升排序。
思路:
如果直接按照题目模拟时间复杂度是 O(mn log(n) ) 显然会TLE的,那么我们考虑优化。

我们知道,如果一个操作是op1,r1,而后面有一个操作 op2,r2, 当r2 >= r1的时候,前一个操作显然是无意义的。那么我们可以用一个严格递减的单调栈来维护有意义的操作,然后把能改变到的数字放到一个multiset里,我们按照r从大到小处理,每一次只处理和上一个r的差值区间即可,通过multiset可以访问一段数字中最大值和最小值来分类处理不同的操作。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int* p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int n,m;
int a[maxn];
stack<pii> b;
multiset<int> s;
std::vector<pii> v;
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    gbtb;
    cin>>n>>m;
    repd(i,1,n)
    {
        cin>>a[i];
    }
    int op,r;
    int q=0;
    repd(i,1,m)
    {
        cin>>op>>r;
        while(!b.empty()&&b.top().se<=r)
        {
            b.pop();
        }
        b.push(mp(op,r));
        q=max(q,r);
    }
    repd(i,1,q)
    {
        s.insert(a[i]);
    }
    v.push_back(mp(0,0));
    while(!b.empty())
    {
        v.push_back(b.top());
        b.pop();
    }
    int last=q;
    for(int j=sz(v)-2;j>=0;--j)
    {
        op=v[j+1].fi;
        for(int i=last;i>=v[j].se+1;i--)
        {
            if(op==1)
            {
                auto it=s.end();
                it--;
                a[i]=*it;
                s.erase(it);
            }else
            {
                a[i]=(*(s.begin()));
                s.erase(s.begin());
            }
        }
        last=v[j].se;
    }
    repd(i,1,n)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}

原文地址:https://www.cnblogs.com/qieqiemin/p/11336402.html

时间: 2024-10-11 11:40:17

Codeforces Round #344 (Div. 2) 631 C. Report (单调栈)的相关文章

Codeforces Round #305 (Div. 2)D---Mike and Feet(单调栈)

Mike is the president of country What-The-Fatherland. There are n bears living in this country besides Mike. All of them are standing in a line and they are numbered from 1 to n from left to right. i-th bear is exactly ai feet high. A group of bears

Codeforces Round #333 (Div. 1)--B. Lipshitz Sequence 单调栈

题意:n个点, 坐标已知,其中横坐标为为1~n. 求区间[l, r] 的所有子区间内斜率最大值的和. 首先要知道,[l, r]区间内最大的斜率必然是相邻的两个点构成的. 然后问题就变成了求区间[l, r]内所有子区间最大值的和. 这个问题可以利用单调栈来做. 每次找到当前点左面第一个大于当前值的点, 然后更新答案. 姿势很多. 1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import

Codeforces Round #172 (Div. 1) BMaximum Xor Secondary 单调栈

//给一个长度为N的个不相同的序列,找出所有区间中最大值和第二大数的异或值最大的值 //对于所有区间只需要找其最大值和第二大数,所以对于很多区间的结果是重复的 //对于每一个数,它起作用的区间只有在其前面最多只有一个数是大于它的 //可以用一个单调递减栈来做,对于每一个新的数a[i],在它前面第一个大于它的数a[j] //和第二个大于它的数之间的数到a[i]的区间的数的最大值和第二大数为a[j] , a[i] //只需要找a[i],a[j]的所有区间所有情况 #include<cstdio>

Codeforces Round #344 (Div. 2) C. Report

Report 题意:给长度为n的序列,操作次数为m:n and m (1 ≤ n, m ≤ 200 000) ,操作分为t r,当t = 1时表示将[1,r]序列按非递减排序,t = 2时表示将序列[1,r]按非递增排序:输出m次操作后的序列? 思路:由于排序是前缀排序,那么前面的操作ti,ri;如果 ri <= rj;那么第i次操作直接被覆盖了.这样我们可以知道有用的排序操作ri是按照严格递减的:并且这时在ri 与r(i + 1)之间的数与后面的操作无关了~~(线性处理),这就直接说明了只需要

Codeforces Round #344 (Div. 2) C. Report 水题

#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) #define rep(i,a,b) for(int i=a;i>=b;i--) #define RI(x) scanf("%d",&x) #define RII(x,y) scanf("%d%d",&x,&y) #d

Codeforces Round #344 (Div. 2)

水 A - Interview 注意是或不是异或 #include <bits/stdc++.h> int a[1005], b[1005]; int main() { int n; scanf ("%d", &n); for (int i=0; i<n; ++i) { scanf ("%d", a+i); } for (int i=0; i<n; ++i) { scanf ("%d", b+i); } int a

Codeforces Round #344 (Div. 2) E. Product Sum 二分斜率优化DP

E. Product Sum Blake is the boss of Kris, however, this doesn't spoil their friendship. They often gather at the bar to talk about intriguing problems about maximising some values. This time the problem is really special. You are given an array a of

Codeforces Round #344 (Div. 2)(按位或运算)

Blake is a CEO of a large company called "Blake Technologies". He loves his company very much and he thinks that his company should be the best. That is why every candidate needs to pass through the interview that consists of the following probl

Codeforces Round #279 (Div. 2) ABCD

Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name     A Team Olympiad standard input/output 1 s, 256 MB  x2377 B Queue standard input/output 2 s, 256 MB  x1250 C Hacking Cypher standard input/output 1 s, 256 MB  x740 D Chocolate standard input/