題目
背景
面對螞蟻們的瘋狂進攻,小FF的Tower defence宣告失敗……人類被螞蟻們逼到了Greed Island上的一個海灣。現在,小FF的後方是一望無際的大海, 前方是變異了的超級螞蟻。 小FF還有大好前程,他可不想命喪於此, 於是他派遣手下最後一批改造SCV佈置地雷以阻擋螞蟻們的進攻。
描述
小FF最後一道防線是一條長度爲N的戰壕, 小FF擁有無數多種地雷,而SCV每次可以在[ L , R ]區間埋放同一種不同於之前已經埋放的地雷。 由於情況已經十萬火急,小FF在某些時候可能會詢問你在[ L’ , R’] 區間內有多少種不同的地雷, 他希望你能儘快的給予答覆。
對於30%的數據: ;
對於100%的數據: .
輸入
第一行爲兩個整數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
解題思路
對於一個區間 ,同一種地雷佈置有六種可能:
顯然我們需要統計進答案的只有2、3、4、6這四種區間,也就是說需要排除掉1、5這兩種區間。
我們發現,如果我們統計了左端點在R及其以前的所有區間,就排除掉了5區間;同理,統計了右端點在L及其以後的所有區間,就排除掉了1區間。因此,答案即爲
如何求的這兩個值呢?我們用兩個樹狀數組分別記錄佈雷區間的左端點和右端點,則兩次前綴和相減即可。
複雜度
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;
}