CF631C Report

该博客详细介绍了CF631C题目的解题思路,通过分析得出对于某些操作可以忽略,重点在于利用单调栈处理序列转化为单调降序,并用优先队列(大根堆和小根堆)处理相邻操作间的区间单调性。通过实例和图解辅助理解算法实现,总复杂度为O(n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

题目大意

给出一个长度为 n n n 的序列 a a a,并且有 m m m 个操作,每个操作包含一个 t i t_i ti r i r_i ri。若 t i = 1 t_i=1 ti=1,则将 a a a 中前 r i r_i ri 个从小到大排序。若 t i = 2 t_i=2 ti=2,则将 a a a 中的前 r i r_i ri 个从大到小排序。

求最终的序列 a a a

Solution

首先有一个显而易见的结论,如果某个操作之后有一个 r r r 大于等于该操作,那么当前操作相当于白给,因为之后会被覆盖。(这与 t t t 无瓜)

因此,我们总是可以将任意序列转化成一个 r r r 单调降序的序列。这个只要用单调栈维护就可以了,这里不再赘述,复杂度 O ( n ) O(n) O(n)

然后考虑任意相邻的两个操作 o p i op_i opi o p i + 1 op_{i+1} opi+1。显然,前者的 r r r 一定是大于后者的,那么在它们之间的区间内,其单调性必然是依赖于 o p i op_i opi t t t 的。就可以用优先队列维护。

这么说比较抽象,所以来看图吧。
在这里插入图片描述

每次操作我们只需要维护右图中黑色部分就可以了,显然,这部分就是整段的最大部分,而要维护最大还是最小是与操作的 t t t 相关的。比如上图就是给出了 o p i op_i opi t t t 1 1 1 o p i + 1 op_{i+1} opi+1 t t t 2 2 2 的情况。

因此需要一个大根堆和小根堆来维护。

Code

#include<bits/stdc++.h>
#define ll long long
#define inf 1<<30
#define INF 1ll<<60
using namespace std;
int read(){
	int w=0,f=1; char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9'){w=w*10+c-'0';c=getchar();}
	return w*f;
}
const int MAXN=2e5+10;
struct node{
	int t,r;
	void input(){
		t=read();r=read();
	}
}stk[MAXN];
int top,a[MAXN];
priority_queue<int> ge;
priority_queue<int,vector<int>,greater<int> > le;
int main()
{
	int n=read(),m=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	for(int i=1;i<=m;i++){
		node tmp;tmp.input();
		while(top&&stk[top].r<=tmp.r) top--;
		stk[++top]=tmp;//单调栈维护严格下降序列
	}
	for(int i=1;i<=stk[1].r;i++)
		le.push(a[i]),ge.push(a[i]);//由于只有前最大的 r 个数会参与,所以优先队列只存前 stk[1].r 个
	int p=stk[1].r;
	stk[top+1].r=0;
	for(int i=1;i<=top;i++){
		int T=stk[i].r-stk[i+1].r;
		while(T--){
			if(stk[i].t==1)
				a[p]=ge.top(),ge.pop();//选取最大的填入
			else a[p]=le.top(),le.pop();
			p--;
		}
	}
	for(int i=1;i<=n;i++) printf("%d ",a[i]);
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值