b_vj_Count Color(线段树+二进制表示颜色)
有一条被划分为L个线段的绳子,有T种颜色可选,且会有两种操作 (1<=L<=100000),T(1<=T<=30):
- 将绳子的区间[a,b]染成颜色c
- 统计绳子区间[a,b]中不同的颜色的数量
思路:tag[k]标记结点k的颜色
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
const int N=100010;
int a[N<<3],tag[N<<3];
void down(int k) {
if (tag[k]) {
a[k<<1]=a[k<<1|1]=tag[k<<1]=tag[k<<1|1]=tag[k];
tag[k]=0;
}
}
void up(int k) {
a[k]=a[k<<1]|a[k<<1|1];
}
void update(int ql, int qr, int l, int r, int k, int c) {
if (ql<=l && r<=qr) {
a[k]=tag[k]=c;
return;
}
down(k);
int m=l+r>>1, ans=0;
if (m>=ql) update(ql,qr,l,m,k<<1,c);
if (m<qr) update(ql,qr,m+1,r,k<<1|1,c);
up(k);
}
int ask(int ql, int qr, int l, int r, int k) {
if (ql<=l && r<=qr)
return a[k];
down(k);
int m=l+r>>1, st=0;
if (m>=ql) st|=ask(ql,qr,l,m,k<<1);
if (m<qr) st|=ask(ql,qr,m+1,r,k<<1|1);
return st;
}
int count_color(int mask) {
int cnt=0;
while (mask>0) {
if (mask&1) cnt++;
mask>>=1;
}
return cnt;
}
int main() {
int n,m,T; scanf("%d %d %d",&n,&T,&m);
for(int i=1; i<=4*n; i++) a[i]=1;
memset(tag,0,sizeof(tag));
while (m--) {
getchar();
char t; scanf("%c", &t);
if (t=='C') {
int l,r,c; scanf("%d %d %d",&l,&r,&c);
if (l>r) swap(l,r);
update(l,r,1,n,1,1<<(c-1));
} else {
int l,r; scanf("%d %d",&l,&r);
if (l>r) swap(l,r);
printf("%d\n", count_color(ask(l,r,1,n,1)));
}
}
return 0;
}