序列操作 - 题目 - Daimayuan Online Judge
问题描述:
思路:首先想的是第二次操作的y
可以将前面所以操作进行抵消,只需要第二次操作的最大值即可。但是发现,对于第一个操作,它是单点修改,每修改一次对于第二次操作都是有影响的,导致不能直接用第二次操作的最大值,因为可能在中间的第一次操作中,使其大于或小于y
。
但是如果将第一次操作的影响去掉就一定可以用最大的第二操作值y
来覆盖前面所有。可以知道,对于下标i
,无论第一个操作进行了多少次,它的最后结果只跟ma
和最后一个y
有关。因此,可以将操作q离线操作,倒叙处理。
- 如果是第二个操作,则更新第二个操作的最大值
- 如果是第一个操作,由于只用操作一次第一个操作,所以判断是否已经进行过第一次操作,如果进行过,则跳过;否则,则将下标
i
元素赋为max(ma, y)
。
具体代码:
void solve() {
int n,m; cin>>n>>m;
vector<int> a(n + 1);
for(int i = 1; i <= n; ++i) cin>>a[i];
vector<array<int,3>> ask(m); // opt x y
for(auto &t: ask) {
cin>>t[0];
if(t[0] == 1) cin>>t[1]>>t[2];
else cin>>t[1];
}
int ma = -INF;
vector<int> vis(n + 1), ans(n + 1);
for(int i = m-1; i >= 0; --i) {
auto ak = ask[i];
if(ak[0] == 1 && !vis[ak[1]]) {
vis[ak[1]] = 1;
ans[ak[1]] = max(ma, ak[2]);
}
if(ak[0] == 2) ma = max(ma, ak[1]);
}
for(int i = 1; i <= n; ++i) if(!vis[i]) ans[i] = max(a[i], ma);
for(int i = 1; i <= n; ++i) cout<<ans[i]<<" ";
}