Codeforces Round #771 E

E. Colorful Operations

对于一个序列 有三种操作:
1.将[l,r]区间颜色修改为c
2.将所有c颜色的+x
3.单点查询
操作1好说是个区间修改 操作2就有点逆天了 那我们考虑简化操作2 我们可以列一个数组color 每次操作2 就相当于color[c]+=x;
那么我们操作1 自然在修改的时候就要 加上当前c的再减去改后c的color里面的值即可
但是这个区间修改1 可以想到不是普通的线段树区间修改 他要是颜色不同的话 会递归到最下面 而且会有很多区间
但是他最多的区间产生就是m个 这样想岂不是qmlogm 其实不然 他每次到达m后 要是做一次就会回归1 所以总和不会超过2m 时间复杂度是O(q+qlogm)
注意我们修改时必须要修改same==1的区间

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
const int M = 998244353;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
#define ls (2*rt)
#define rs (2*rt + 1)
struct node{
    int l,r,same,lz,col;
}tree[N<<2];
int color[1000010],ans;
void pushup(node &u,node &l,node &r){
    if(l.col==r.col&&l.same&&r.same){
        u.same=1;
        u.col=l.col;
    }else u.same=0;
}
inline void pushup(int u){
    pushup(tree[u],tree[u<<1],tree[u<<1|1]);
}
void pushdown(int i){
    if(tree[i].same!=0){
        tree[i<<1].lz+=tree[i].lz,tree[i<<1|1].lz+=tree[i].lz;//我们只用单点查询 所以不用保证中间节点的正确性
        tree[i<<1].col=tree[i].col,tree[i<<1|1].col=tree[i].col;
        tree[i].lz=0;
    }
}
inline void build(int i,int l,int r){
    tree[i].l=l;tree[i].r=r;
    if(l==r){
        tree[i].col=tree[i].same=1;
        return ;
    }
    int mid=l+r>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    pushup(i);
}
void modify(int i,int l,int r,int k){
    if(tree[i].r<=r && tree[i].l>=l&&tree[i].same){
        tree[i].lz += color[tree[i].col];
        tree[i].col = k;
        tree[i].lz -= color[tree[i].col];
        return ;
    }
    pushdown(i);
    if(tree[i<<1].r>=l)modify(i<<1,l,r,k);
    if(tree[i<<1|1].l<=r)modify(i<<1|1,l,r,k);
    pushup(i);
}

inline node query(int i,int l,int r){
    //if(l>r)return{0};
    node s;
    if(tree[i].l>=l && tree[i].r<=r){
        ans=color[tree[i].col];
        return tree[i];
    }
    pushdown(i);
    if (tree[i<<1].r>=r)  s= query(i<<1,l,r);
    else if(tree[i<<1|1].l<=l) s= query(i<<1|1,l,r);
    else{
        auto left = query(i<<1,l,r);
        auto right= query(i<<1|1,l,r);
        node res;
        pushup(res,left,right);
        return res;
    }
    return s;
}
void solve() {
    int n,m;cin>>n>>m;
    build(1,1,n);
    while(m--){
        char op[10];cin>>op;
        if(op[0]=='C'){
            int l,r,k;cin>>l>>r>>k;
            modify(1,l,r,k);
        }else if(op[0]=='A'){
            int x,k;cin>>x>>k;
            color[x]+=k;
        }else{
            int x;cin>>x;
            cout<<query(1,x,x).lz+ans<<endl;
        }
    }
}
signed main(){
    fast
    int T;T=1;
    while(T--) {
        solve();
    }
    return ~~(0^_^0);
}
posted @ 2022-09-04 20:59  ycllz  阅读(25)  评论(0)    收藏  举报