问的就是 每次给你区间 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
",a);
}
}
return 0;
}