codeforces 1198B

题目链接:http://codeforces.com/problemset/status

题目大意为有n个市民,每个市民有ai点数财富,以下有q次操作,操作类型为两类,1类:把第p个市民的财富改为x,2类:把所有财富小于x的市民的财富变为x。

题目数据量较大,强行n^2暴力模拟会超时,分析题意尝试缩小时间复杂度。观察到在对第i个市民进行最后一次1类操作之后,将不会影响此后的所有第2类操作,也就是说如果此后的第2类操作的x > ai的财富,将可以修改第i个市民的财富,因此每个市民的最终财富 = 对该市民的最后一次第1类操作和此后的第2类操作 两者之间的最大值即可。用ops[]数组记录第1类操作的顺序,opsmoney记录第2类操作的财富,q次操作从后往前遍历,做opsmoney[ i ] = max (opsmoney[ i ] ,opsmoney[ i +1 ])的更新,记录第i次操作之后 x 的最大值,方便后续比较,具体看代码。

AC代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
long long int ops[200005];
long long int opsmoney[200005];
long long int money[200005];
int main()
{
	int n;
	cin>>n;
	for(int i = 0;i<n;i++){
		cin>>money[i];
	}
	long long int q;
	cin>>q;
	memset(opsmoney,0,sizeof(opsmoney));
	memset(ops,0,sizeof(ops));
	for(int i = 0;i<q;i++){
		int flag;
		cin>>flag;
		if(flag == 1){
			long long int p;
			long long int x;
			cin>>p;
			cin>>x;
			ops[p-1] = i;
			money[p-1] = x; 
		}
	    if(flag == 2){
			long long int x;
			cin>>x;
			opsmoney[i] = x;
		}
	}
	for(int i = q-1;i>=0;i--){
		opsmoney[i] = max(opsmoney[i],opsmoney[i+1]);
	}
	for(int i = 0;i<n;i++){
		money[i] = max(money[i],opsmoney[ops[i]]);
	}
	for(int i = 0;i<n;i++){
		if(!i){
			cout<<money[i];
		}
		else{
			cout<<" "<<money[i];
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/AaronChang/p/12129651.html