Colorful Operations (CF2D) (线段树,对连续相同标记的一段进行lz的01处理+均摊思想+前缀和处理(用到才更新,不实时更新))

 

 思路:

  • 形式上就很像线段树, 在染色的时候, 关键是对相同颜色的权值一起加,
  • 这个地方要用前缀和处理, 因为没有要求加一次就要实时更新, 于是就用到了在更新,如何更新呢? 就利用前缀和
  • 然后 修改一个区间, 先把这个区间本来的颜色值更新,在减去当前的颜色值, 因为这个时候是从当时开始算的
  • 而且这个修改内的区间颜色不同的时间复杂度是均摊的, 可以举例让每一次都是 1-n, 或者是 1,1, 2,2;
  • 查找同理可得
#include <bits/stdc++.h>
using namespace std;
#define M 1000005
#define ri register int 

int n,m;
long long val[M];
int col[M];
struct dian{
    int col;
    int fg;
    long long val;
    long long lz;
    int l,r;
}p[M*4];
void build(int i,int l,int r)
{
    p[i].l=l,p[i].r=r;p[i].col=1;
    if(l==r)
    {
        p[i].col=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
}
void down(int i)
{
    p[i].fg=0;
    p[i<<1].lz+=p[i].lz;
    p[i<<1|1].lz+=p[i].lz;
    p[i].lz=0;
    p[i<<1].col=p[i].col;
    p[i<<1|1].col=p[i].col;
    p[i<<1].fg=1;
    p[i<<1|1].fg=1;
}
void xiu(int i,int l,int r,int c)
{
    if(l>p[i].r||r<p[i].l) return ;
    if(l<=p[i].l&&p[i].r<=r&&p[i].col)
    {
        p[i].lz+=val[p[i].col];
        p[i].lz-=val[c];
        p[i].col=c;
        p[i].fg=1;
        return ;
    }
    if(p[i].fg) down(i);
    xiu(i<<1,l,r,c);
    xiu(i<<1|1,l,r,c);
    if(p[i<<1].col==p[i<<1|1].col) p[i].col=p[i<<1].col;
    else p[i].col=0;
}
long long qu(int i,int l,int r)
{
    if(l>p[i].r||r<p[i].l) return 0;
    if(l<=p[i].l&&p[i].r<=r)
    {
        col[p[i].l]=p[i].col;
        return p[i].lz;
    }
    if(p[i].fg) down(i);
    return qu(i<<1,l,r)+qu(i<<1|1,l,r);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    cin>>n>>m;
    build(1,1,n);
    for(ri i=1;i<=n;i++) col[i]=1;
    
    for(ri i=1;i<=m;i++)
    {
        string op;
        cin>>op;
        if(op=="Color")
        {
             int a,b,c;
             cin>>a>>b>>c;
             xiu(1,a,b,c);
        }
        if(op=="Add")
        {
            int a,b;
            cin>>a>>b;
            val[a]+=b;
        }
        if(op=="Query")
        {
            int a;
            cin>>a;
            long long tmp=qu(1,a,a);
            tmp+=val[col[a]];
            cout<<tmp<<"\n";
        }
    }
    return 0;
} 
View Code

后记:

  • 线段树 是4 倍 空间
posted @ 2022-11-23 17:12  VxiaohuanV  阅读(25)  评论(0编辑  收藏  举报