1 2 3 4

洛谷 贪婪大陆--线段树

问的就是 每次给你区间  l--r,每次覆盖一种不同的颜色,查询l--r有多少种不同的颜色

 

这个问题本质是在问区间l--r有多少不同的区间,利用前缀和计算一下,具体看代码

 

 

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 2e5+111;
typedef long long ll;
struct Node{
	ll val,l,r;
	ll lazy;
}tree[3][maxn*4];

int push(int id,int node,int be,int en){
	int mid = be + en >> 1;
	int l = node*2;
	int r = node*2+1;
	if(tree[id][node].lazy){
		tree[id][l].val += (mid - be + 1)*tree[id][node].lazy;
		tree[id][r].val += (en - mid)*tree[id][node].lazy;
		
		tree[id][l].lazy += tree[id][node].lazy;
		tree[id][r].lazy += tree[id][node].lazy;
		tree[id][node].lazy = 0;
	}
	return 0;
}
int update(int id,int node,int be,int en,int LL,int RR,int val){
	int mid = be + en >> 1;
	int l = node*2;
	int r = node*2+1;
	if(LL <= be && en <= RR){
		tree[id][node].val += (en - be + 1)*val;
		tree[id][node].lazy += val;
		return 0;
	}
	push(id,node,be,en);
	if(LL <= mid) update(id,l,be,mid,LL,RR,val);
	if(RR > mid) update(id,r,mid+1,en,LL,RR,val);
	tree[id][node].val = tree[id][l].val + tree[id][r].val;
	return 0;
}
int ask(int id,int node,int be,int en,int LL,int RR){
	if(LL == 0 || RR == 0) return 0;
	int mid = be + en >> 1;
	int l = node*2;
	int r = node*2+1;
	if(LL <= be && en <= RR){
		return tree[id][node].val;
	}	
	push(id,node,be,en);
	ll a=0,b=0;
	if(LL <= mid) a = ask(id,l,be,mid,LL,RR);
	if(RR > mid)  b = ask(id,r,mid+1,en,LL,RR);
	return a+b; 
}

int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++){
		int op;
		scanf("%d",&op);
		if(op == 1){//覆盖 
			int x,y;
			scanf("%d%d",&x,&y);
			update(0,1,1,n,y+1,n,1);//前缀 
			update(1,1,1,n,x,y,1);
		}
		else{
			int x,y;
			scanf("%d%d",&x,&y);
			ll a = ask(0,1,1,n,y,y) - ask(0,1,1,n,x,x);
			a += ask(1,1,1,n,y,y);
			printf("%lld\n",a);
		}
	}
	return 0;
} 

  

posted @ 2020-11-11 20:22  Lesning  阅读(84)  评论(0编辑  收藏  举报