洛谷P2161 [SHOI2009]会场预约 线段树染色

题目链接:https://www.luogu.com.cn/problem/P2161

本题有好多做法,什么平衡树呀,STL呀,无奈蒟蒻的我只能用线段树染色来做。
每次A操作,把一个区间给染色了,如果那个区间之前被染色过,就要被删除,这里我们不直接删除,而是用 del数组 标记一下该颜色已被删除即可。我们需要在标准区间更新线段的基础加上一个 update 函数,当我们要染色的区间包含了当前区间,就用 update 函数将该区间全部染成新颜色,并更新总颜色和删除颜色的数量。我们还要用 vis 数组判断一个区间是否是同一种颜色,如果是同一种颜色,即可直接染色,如果不是而要继续向下找。注意,标记下传的时候,别忘了把原来颜色给改为无色,防止以后重复下传(有wa的经历 qwq)。
B操作,直接输出
代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=4e5+5;
int tree[maxn];//子树的颜色
bool vis[maxn];//子树是否具有相同颜色
bool del[maxn];//该颜色是否被删除
char opt[2];//选择
int st,ed;//区间头与尾
int ans,era;//未被删除的颜色数量
//被删除的颜色数量
int cnt;//颜色编号
void push_down(int l,int r,int k)//标记下传
{
    vis[k]=false;//若是下传了,
    //说明子树肯定不是相同颜色
    //(因为新增了一种颜色)
    if(!tree[k])
    return ;//无色不用下传
    tree[k<<1]=tree[k<<1|1]=tree[k];//下传颜色
    tree[k]=0;//标记已下传
    //改为无色,防止以后重复下传
}
void build(int l,int r,int k)//建树
{
    vis[k]=true,tree[k]=0;//初始全都为一个颜色
    //即无色(==0)
    if(l==r)
    return ;
    int mid=(l+r)>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
}
void update(int l,int r,int k)//染色
{
    if(vis[k])//子树颜色相同,直接染色
    {
        if(!del[tree[k]]&&tree[k])
        //未被删除且不是无色
        ans--,era++;//总颜色-1,删除颜色+1
        del[tree[k]]=true;//删除该颜色
        tree[k]=cnt;//染色
        return ;
    }
    int mid=(l+r)>>1;
    update(l,mid,k<<1);
    update(mid+1,r,k<<1|1);
    vis[k]=1,tree[k]=cnt;//该区间全染成新颜色
}
void modify(int l,int r,int k)//区间更新
{
    if(l>=st&&ed>=r)
    //该区间要全部染成新颜色
    {
        update(l,r,k);//染色
        return ;
    }
    push_down(l,r,k);
    int mid=(l+r)>>1;
    if(st<=mid)
    modify(l,mid,k<<1);
    if(ed>mid)
    modify(mid+1,r,k<<1|1);
}
int main()
{
    int n;//操作次数
    scanf("%d",&n);
    build(1,100000,1);//建树
    for(int i=1;i<=n;i++)
    {
        scanf("%s",opt);
        if(opt[0]=='B')
        {
            printf("%d\n",ans);
        }
        else
        {
            scanf("%d %d",&st,&ed);
            cnt++,ans++;//新增了一种颜色,数量+1,编号+1
            era=0;//此次操作删除颜色数量初始为0
            modify(1,100000,1);
            printf("%d\n",era);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章