P1558 色板游戏

 

>>>

然后发现颜色范围好像只有30;

所以,我就想到一种sao操作,搞30颗线段树。

每颗线段树代表一种颜色。

那么对于题中的两种操作:

1.修改。我们for循环扫一遍所有颜色,把其他颜色的线段树l->r修改成0,要修改的颜色所对应的线段树改成1。

2.询问。也是for循环,如果l->r这个区间的第k种颜色所对应的线段树有值,则ans++。

时间复杂度也很低,大概是(MLlog(L)*T).

>>>线段树 只是 线性结构  query/change/areaAdd/areaMull 都是在add mul sum 处理

而 pushdown 则是对 add mul sum 进行下放处理

 

::: res->0

:::build(1,1,1,l) 初始状态只有 1 号颜色

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------debug\n");
using namespace std;
const int maxn=1e5+10;

int sum[33][maxn<<2],cln[33][maxn<<2];
int l,t,o;

void build(int tp,int k,int l,int r)
{
    if(l==r)
    {
        sum[tp][k]=1;
        return;
    }
    int mid=l+r>>1;
    build(tp,k<<1,l,mid);
    build(tp,k<<1|1,mid+1,r);
    sum[tp][k]=sum[tp][k<<1]+sum[tp][k<<1|1];
}
void pushdown(int tp,int k)
{
    if(cln[tp][k]==0) return;
    if(cln[tp][k]==-1){
        sum[tp][k<<1]=sum[tp][k<<1|1]=0;
        cln[tp][k<<1]=cln[tp][k<<1|1]=-1;
    }
    else{
        sum[tp][k<<1]=sum[tp][k<<1|1]=1;
        cln[tp][k<<1]=cln[tp][k<<1|1]=1;
    }
    cln[tp][k]=0;
}

void change(int tp,int k,int l,int r,int x,int y,int val)//cln -> 标记 
{
    if(l>y||r<x) return;// sum -> 区间和的标记 
    if(x<=l&&r<=y)
    {
        if(val==0) sum[tp][k]=0,cln[tp][k]=-1;
        else sum[tp][k]=cln[tp][k]=1;
        return;
    }
    pushdown(tp,k);
    int mid=l+r>>1;
    if(x<=mid) change(tp,k<<1,l,mid,x,y,val);//会一直处理下去,直到 sum的 全更新 
    if(mid<=y) change(tp,k<<1|1,mid+1,r,x,y,val);
    sum[tp][k]=sum[tp][k<<1]+sum[tp][k<<1|1];
}
int query(int tp,int k,int l,int r,int x,int y)
{
    if(l>y||r<x) return 0;
    if(x<=l&&r<=y)    return sum[tp][k];
    pushdown(tp,k);
    
    int mid=l+r>>1,res=0;//res -> 0 or 栈存储 无限 存贮 
    if(x<=mid) res+=query(tp,k<<1,l,mid,x,y);
    if(mid<=y) res+=query(tp,k<<1|1,mid+1,r,x,y);
    return res;
}
int main()
{
    //ios::sync_with_stdio(false); cin.tie(0);
    scanf("%d%d%d",&l,&t,&o); //cin>>l>>t>>o;
    //for(int i=1;i<=t;i++) 
    build(1,1,1,l);
    
    //cout<<o<<endl;
    
    for(int i=1;i<=o ;i++)
    {
        char s[3]; int a,b;
        scanf("%s%d%d",s,&a,&b); if(a>b) swap(a,b);//
        if(s[0]=='C'){
            int v; scanf("%d",&v);
            for(int j=1;j<=t;j++){
                if(j==v) change(j,1,1,l,a,b,1);
                else change(j,1,1,l,a,b,0);
            }
        }
        else{
            int ans=0;
            for(int j=1;j<=t;j++)
                if(query(j,1,1,l,a,b)) ans++;
    
            printf("%d\n",ans);
        }
    }
    return 0;
}
View Code

 

 
posted @ 2023-08-10 00:47  JMXZ  阅读(9)  评论(0)    收藏  举报