[luogu2184] 貪婪大陸 (樹狀數組)

題目

背景

面對螞蟻們的瘋狂進攻,小FF的Tower defence宣告失敗……人類被螞蟻們逼到了Greed Island上的一個海灣。現在,小FF的後方是一望無際的大海, 前方是變異了的超級螞蟻。 小FF還有大好前程,他可不想命喪於此, 於是他派遣手下最後一批改造SCV佈置地雷以阻擋螞蟻們的進攻。

描述

小FF最後一道防線是一條長度爲N的戰壕, 小FF擁有無數多種地雷,而SCV每次可以在[ L , R ]區間埋放同一種不同於之前已經埋放的地雷。 由於情況已經十萬火急,小FF在某些時候可能會詢問你在[ L’ , R’] 區間內有多少種不同的地雷, 他希望你能儘快的給予答覆。
對於30%的數據: 0n,m1000 ;
對於100%的數據: 0n,m105 .

輸入

第一行爲兩個整數n和m;n表示防線長度, m表示SCV佈雷次數及小FF詢問的次數總和。
接下來有m行, 每行三個整數Q,L , R; 若Q=1 則表示SCV在[ L , R ]這段區間布上一種地雷, 若Q=2則表示小FF詢問當前[ L , R ]區間總共有多少種地雷。

輸出

對於小FF的每次詢問,輸出一個答案(單獨一行),表示當前區間地雷總數。

樣例輸入

5 4
1 1 3
2 2 5
1 2 4
2 3 5

樣例輸出

1
2

解題思路

對於一個區間[L,R] ,同一種地雷佈置有六種可能:
這裏寫圖片描述
顯然我們需要統計進答案的只有2、3、4、6這四種區間,也就是說需要排除掉1、5這兩種區間。
我們發現,如果我們統計了左端點在R及其以前的所有區間,就排除掉了5區間;同理,統計了右端點在L及其以後的所有區間,就排除掉了1區間。因此,答案即爲

(1)[R][L]

如何求的這兩個值呢?我們用兩個樹狀數組分別記錄佈雷區間的左端點和右端點,則兩次前綴和相減即可。
複雜度O(nlog2n)

Code

#include<cstdio>

using namespace std;

const int N = 100005;
int n, m, opt, ql, qr, cl[N], cr[N];

inline int lowbit(int x){return x & -x;}
inline int query(int x, int c[]){
    int res = 0;
    while(x > 0){
        res += c[x];
        x -= lowbit(x);
    }
    return res;
}
inline void add(int x, int val, int c[]){
    while(x <= n){
        c[x] += val;
        x += lowbit(x);
    }
}

int main(){
    scanf("%d%d", &n, &m);
    while(m--){
        scanf("%d%d%d", &opt, &ql, &qr);
        if(opt == 1){
            add(ql, 1, cl);
            add(qr, 1, cr);
        }
        else if(opt == 2)
            printf("%d\n", query(qr, cl) - query(ql-1, cr));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章