#452. 序列操作

序列操作 - 题目 - Daimayuan Online Judge

问题描述:

#452. 序列操作_第1张图片

思路:首先想的是第二次操作的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]<<" ";
}

你可能感兴趣的:(算法题,算法)