CF 1198B Welfare State 思维

题目要求处理n个数字的数组,面对两类操作:更新指定位置的值和将所有小于特定值的元素设为该值。解决方法是从后往前遍历操作,记录每次2类操作的最大值,并根据1类操作更新每个元素的最终值。首次遇到的下标p更新为其最大值,无1类操作的下标设为原值与最大值的较大者。
摘要由CSDN通过智能技术生成

传送门

题意:给定n个数字,q次操作,操作分为两种(且称之为1类操作和2类操作),1 p x为把a[p]改为x, 2 x为把数组中所有小于x的数字全部改为x.

思路:对于有1类操作1 p x更新的p,我们只关心它最后一次的1类更新以及它最后一次1类更新之后有无可以改变它的2类更新(例如最后一次对a[3]的操作为a[3]=10,那么我们可以看这次更新后面有无2 x 且x>10. ). 于是我们将q次操作从后往前遍历,并记录2类操作的最大x值(设为maxn). 对于第一次遇到某个下标p(从后往前遍历第一次遇到的p也就是从前往后更新最后一次的p),我们就将它赋值为max(x,maxn),对于没有1类操作的下标,直接将其赋值为max(原值,maxn)即可.

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <time.h>
#include <map>
#include <set>
#define mem(a,x) memset(a,x,sizeof(a))
#define gi(x) scanf("%d",&x)
#define gi2(x,y) scanf("%d%d",&x,&y)
#define gi3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define gll(x) scanf("%lld",&x)
#define gll2(x,y) scanf("%lld%lld",&x,&y)
#define random(x) (rand()%x)
using namespace std;
const double eps=1e-8; 
typedef long long ll;
const int MAXN=200005;
const ll mod=1e9+7;
const int inf=0x3f3f3f3f;
int n;
int a[MAXN];
vector<int>q[MAXN];
int book[MAXN];
int flag[MAXN];
int main(){
	gi(n);
	for(int i=1;i<=n;i++){
		gi(a[i]);
	}
	mem(flag,-1);mem(book,-1);
	int T;
	gi(T);
	for(int i=1;i<=T;i++){
		int t,p,x;
		gi(t);q[i].push_back(t);
		if(t==1){
			gi2(p,x);q[i].push_back(p);
			q[i].push_back(x);
		}
		else{
			gi(x);
			q[i].push_back(x);
		}
	}
	int maxn=-1;
	for(int i=T;i>=1;i--){
		if(q[i][0]==1){
			int p=q[i][1],x=q[i][2];
			if(flag[p]==-1){
				flag[p]=max(maxn,q[i][2]);
			}
		}
		else{
			maxn=max(maxn,q[i][1]);
		}
	}
	for(int i=1;i<=n;i++){
		if(flag[i]==-1){
			flag[i]=max(a[i],maxn);
		}
		printf("%d ",flag[i]);
	}	
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值