452. 序列操作
题意 | 简单
给你一个长度为
n
n
n 的序列 a1, a2,…, an
你需要进行两种操作:
- 1 x y 将第 x x x 个数变为 y y y ;
- 2 y 将所有小于 y y y 的数修改为 y y y ;
一共执行 q q q 次操作,输出执行完所有操作后的序列。
1 ≤ \leq ≤ n , q n,q n,q ≤ \leq ≤ 1 e 6 1e^6 1e6 , 1 ≤ \leq ≤ ai ≤ \leq ≤ 1 0 9 10^9 109
思路 | 思维
第一种操作是强制进行的,所以这个操作只需要记每一个位置上的最后一次的修改就可以了
第二种操作是在最后一次第一次操作的后面,用一个后缀数组记一下最大值就好了
然后可以把原本每一个位置上的 ai 当作第0次第一种操作放进去。
代码
#include <iostream>
#include <queue>
#include <vector>
#include <cmath>
#include <vector>
#include <map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
#define int long long
const int maxn = 1e6 + 10;
int a[maxn];
struct node {
int id, x;
}maxx[maxn];
vector<node>g[maxn];
int tol[maxn];
int ans[maxn];
void solve() {
int n, q; cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> a[i], g[i].push_back({ 0,a[i] });
int cnt = 0, pos = 0;
while (q--) {
cnt++;
int op; cin >> op;
if (op == 1) {
int x, y; cin >> x >> y;
g[x].push_back({ cnt,y });
}
else {
int x; cin >> x;
maxx[++pos].id = cnt;
maxx[pos].x = x;
}
}
for (int i = pos; i >= 1; i--) {
tol[i] = max(maxx[i].x, tol[i + 1]);
}
for (int i = 1; i <= n; i++) {
int len = g[i].size();
int tmp = g[i][len - 1].id;
int l = 1, r = pos;
if (tmp > maxx[pos].id) {
ans[i] = g[i][len - 1].x; continue;
}
while (l < r) {
int mid = (l + r) >> 1;
if (maxx[mid].id >= tmp) r = mid;
else l = mid + 1;
}
ans[i] = max(g[i][len - 1].x, tol[r]);
}
for (int i = 1; i <= n; i++) {
cout << ans[i] << " ";
}
cout << endl;
}
signed main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int t; t = 1;
while (t--) {
solve();
}
return 0;
}