P2184 贪婪大陆(线段树 or 树状数组)

题目链接:传送门

思路:一开始一直想使用线段树保存染色信息。。然而发现这种做法非常困难,,然后看了题解,使用树状数组或者线段树维护在位置x的区间起点数量前缀和suma[n]和区间终点数量的前缀和sumb[n]即可 , 比如一段区间[a , b]的炸弹种类就是sumb[b] - suma[a-1]。

代码:(这里使用了线段树)

#include 

using namespace std;

const int maxn = 1e5 + 5;

int sum[4 * maxn] , add[4 * maxn] , sum1[4 * maxn]; 
int x , y , p;



int query(int* obj , int o , int l , int r) {
	if(x <= l && r <= y) {
		return obj[o];
		//cout << "obj = " << obj[o] << "\n";	
	}
	else {
		int mid = (l + r) / 2;
		//push_down(o , l , r);
		int res = 0;
		if(x <= mid) res += query(obj , o << 1 , l , mid);
		if(y > mid)res += query(obj , o << 1 | 1, mid + 1, r);
		return res;
	}
}


void s_update(int* obj , int o , int l ,int r ,int d ) {
	if(l == r) {
		obj[o] += d;
	}
	else {
		int mid = (l + r) / 2;
		if(p <= mid)s_update(obj , o << 1 , l , mid , d);
		else s_update(obj , o << 1 | 1 , mid + 1 , r , d);
		obj[o] = obj[o << 1] + obj[o << 1 | 1];
	}
}

int main() {
	int n , m;
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n >> m;
	x = 1;
	while(m--) {
		int q , a , b;
		cin >> q >> a >> b;
		if(q == 1) {
			p = a;
			s_update(sum , 1 , 1 , n , 1);
			p = b;
			s_update(sum1 , 1 , 1 , n , 1);
		}
		else {
			int t1 , t2;
			y = b;
			t1 = query(sum , 1 , 1 , n);
			y = a - 1;
			t2 = query(sum1 , 1 , 1 , n);
			cout << t1 - t2 << endl;
		}
	}
	
	return 0;
}

你可能感兴趣的:(线段树,思维)