LDUOJ 時間鎖鏈 (狀壓+線段樹 )

時間鎖鏈

時間限制: 1 Sec 內存限制: 128 MB
[命題人:admin] [ Edit] [ TestData]
題目描述
當墨老師找到封閉時間環中最小的逆序對數後,他就可以將時間環展開成一個長L的時間鎖鏈(我們可以將之看成是一根很長的管子),其中L是整數,所以我們可以將該管子分爲L段,並從左到右標記爲1,2,…,L。

現在對管子有兩種操作:

  1. “C A B C” 將A到B的數都標記爲C(我們可形象的看成是染成C這種顏色)。

  2. “P A B” 輸出A和B之間不同顏色的數目。

顏色有T種,標記爲1,2,3…,T,T是一個很小的值,初始時管子的顏色爲1。
輸入
第一行爲L (1≤L≤100 000),T (1≤T≤30)和O (1≤O≤100 000),其中O表示操作數。隨後O行爲操作命令即"C A B C"或"P A B",其中A可能比B值大。
輸出
輸出操作的結果。
樣例輸入 Copy
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2
樣例輸出 Copy
2
1

題意:
題意很簡單,給你一個區間和兩種操作,你可以更改區間的數或是查詢區間裏有多少種不同的數。
思路:
典型的區間修改和區間查詢,用線段樹維護一下就可以了。
因爲顏色的總數目很小,我們可以開一個bool數組暴力記錄(應該可以~),也可以把狀態壓縮成二進制數,表示的含義就是第i位爲1時說明第i個顏色被塗上了。

代碼:
注意一下pushdown的寫法~

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
struct node{
    int l,r;
    int sum;//二進制表示塗了多少種顏色
    int lazy;
}a[maxn];
void pushdown(int u){
    if(a[u].lazy){
        a[u<<1].lazy=a[u<<1|1].lazy=a[u].lazy;
        a[u<<1].sum=a[u<<1|1].sum=(1<<a[u].lazy);
        a[u].lazy=0;
    }
}
void build(int u,int l,int r){
    a[u].l=l;a[u].r=r;
    if(l==r) a[u].sum=1<<1;
    else{
        int mid=(l+r)>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
        a[u].sum=a[u<<1].sum|a[u<<1|1].sum;
    }
}
void update(int u,int z,int l,int r){
    if(a[u].l>r||a[u].r<l) return ;///完全不包含
    if(a[u].l>=l&&a[u].r<=r){//完全包含
        a[u].sum=1<<z;
        a[u].lazy=z;
        return ;
    }
    pushdown(u);
    update(u<<1,z,l,r);update(u<<1|1,z,l,r);
    a[u].sum=a[u<<1].sum|a[u<<1|1].sum;
}
int query(int u,int l,int r){
    if(a[u].l>r||a[u].r<l) return 0;
    if(a[u].l>=l&&a[u].r<=r) return a[u].sum;
    pushdown(u);
    return query(u<<1,l,r)|query(u<<1|1,l,r);
}
int main(){
    int n,t,o;
    cin>>n>>t>>o;
    build(1,1,n);
    while(o--){
        char op;int x,y;
        cin>>op>>x>>y;
        if(op=='P'){
            if(x>y) swap(x,y);
            int res=query(1,x,y);
            int sum=0;
            for(int i=1;i<=t;i++)
                if(res&(1<<i)) sum++;
            cout<<sum<<endl;
        }
        else if(op=='C'){
            int z;
            if(x>y) swap(x,y);
            cin>>z;
            update(1,z,x,y);
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章