洛谷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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章