题解:贪婪大陆

题目传送门

树状数组

我们开两个权值树状数组 \(tl,tr\),分别存储布雷的左、右边界。

那么对于给定区间 \([l,r]\),答案即 \(tl.query(r)-tr.query(l-1)\)

如图:

008

蓝色即布雷区间,黑色即查询区间。

\(\color{black}\colorbox{black}{1}\) 黑色右区间之前的 \(\color{skyblue}\colorbox{skyblue}{1}\) 蓝色左边界所在区间才有可能与 \(\color{black}\colorbox{black}{1}\) 黑色区间重合。

那么我们再减去 \(\color{black}\colorbox{black}{1}\) 黑色区间左边界左边的 \(\color{skyblue}\colorbox{skyblue}{1}\) 蓝色左边界数量(未重合)即可。

AC 代码

//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=1e5;
struct tree{
	int t[N+1];
	
	int lowbit(int x){
		return x&-x;
	}
	void add(int x,int k){
		while(x<=N){
			t[x]+=k;
			x+=lowbit(x);
		}
	}
	int query(int x){
		int ans=0;
		while(x){
			ans+=t[x];
			x-=lowbit(x);
		}return ans;
	}
}tl,tr;
int n,m;
int main(){
	/*freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);*/
	
	scanf("%d %d",&n,&m);
	while(m--){
		int q,l,r;
		scanf("%d %d %d",&q,&l,&r);
		switch(q){
			case 1:
				tl.add(l,1);tr.add(r,1);
				break;
			case 2:
				printf("%d\n",tl.query(r)-tr.query(l-1));
				break;
		}
	}
	
	/*fclose(stdin);
	fclose(stdout);*/
	return 0;
}
posted @ 2025-07-20 18:00  TH911  阅读(4)  评论(0)    收藏  举报