Codeforces 1638 E. Colorful Operations - segment tree + violence, something

Posted by jguy on Wed, 02 Mar 2022 04:02:45 +0100

This way

Meaning:

Give you an array a with length n. at the beginning, the color of all positions is 1 and the value is 0 There are three operations at a time:
Color l r x: change the color of all positions in [l,r] to X
Add c: add c to the values of all positions with color c
Q: what is the value of Query i.

Solution:

This feeling is still a little around. I also thought about it for a long time. Finally, I knocked it after I confirmed my idea through a big guy's code. Otherwise, I broke down and had no reference to make. It's very uncomfortable.
First of all, it's easy to think of the problem of interval transformation as interval modification, but sometimes it's not necessarily, so I hesitated for some time when I decided to do it.
Use multiset to maintain each segment of color. In this way, when color l,r, x, you only need to delete the internal of l,r, and then modify the two ends. The time complexity should be O ( N l o g N ) O(NlogN) O(NlogN), because the interval you delete must be established by one operation, so the complexity is not very large.
so what? For the value-added problem, if we operate all the corresponding color ranges every time, the time complexity will be very high. Therefore, it should be delayed operation at this time.
So how?
sum[i] indicates the sum of the values of color I from the beginning of the operation to the present.
But there must be a situation, that is, what about the newly added colors?
Then notice that the new color we added is in the form of an interval. When I add this color to this interval, I just need to modify the interval. The value of this interval in the segment tree is - sum[i]. Then the sum and the corresponding value of the segment tree will cancel each other.
Then what should we do when color I becomes color j? Then we just need to add sum[i] to the interval. Connected with the above operation, it becomes:
When the color I becomes j, add sum[i] first to get all the previous Add i operations, and then subtract sum[j] to eliminate the influence of Add j operations. In this way, the final value is sum[j] + the value of single point query of segment tree.
It's better to look at the code and explain some variables:
st means to save all current color ranges
col[i] indicates the interval color starting with I
sum[i] represents the sum of the values of color I from the beginning to the present

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+5;
ll s[N*4],f[N*4];
void push_down(int root){
    if(!f[root])return ;
    s[root<<1]+=f[root];
    s[root<<1|1]+=f[root];
    f[root<<1]+=f[root];
    f[root<<1|1]+=f[root];
    f[root]=0;
}
void update(int l,int r,int root,int ql,int qr,ll v){
    if(l>=ql&&r<=qr){
        s[root]+=v;
        f[root]+=v;
        return ;
    }
    push_down(root);
    int mid=l+r>>1;
    if(mid>=ql)update(l,mid,root<<1,ql,qr,v);
    if(mid<qr)update(mid+1,r,root<<1|1,ql,qr,v);
    s[root]=s[root<<1]+s[root<<1|1];
}
ll query(int l,int r,int root,int p){
    if(l==r)return s[root];
    push_down(root);
    int mid=l+r>>1;
    if(mid>=p)return query(l,mid,root<<1,p);
    return query(mid+1,r,root<<1|1,p);
}
#define pii pair<int,int>
const int mx=1e9+7;
multiset<pii>st;
ll sum[N];
int col[N];
int main()
{
    char s[15];
    int n,m,l,r,v;
    scanf("%d%d",&n,&m);
    st.insert({0,0}),st.insert({mx,mx}),st.insert({1,n});
    col[1]=1;
    while(m--){
        scanf("%s",s);
        if(s[0]=='C'){
            scanf("%d%d%d",&l,&r,&v);
            multiset<pii>::iterator it=st.upper_bound({l,mx});it--;
            while(it->first<=r){
                auto [x,y]=*it;
                st.erase(it++);
                if(x<l)st.insert({x,l-1});
                if(y>r)st.insert({r+1,y}),col[r+1]=col[x];
                update(1,n,1,max(l,x),min(r,y),sum[col[x]]);
            }
            st.insert({l,r});
            col[l]=v;
            update(1,n,1,l,r,-sum[v]);
        }
        else if(s[0]=='A')
            scanf("%d%d",&l,&v),sum[l]+=v;
        else{
            scanf("%d",&l);
            multiset<pii>::iterator it=st.upper_bound({l,mx});
            it--;
            printf("%lld\n",query(1,n,1,l)+sum[col[it->first]]);
        }

    }
    return 0;
}

Topics: Algorithm data structure