题意:
n个桶按顺序排列,我们用1~n给桶标号。有两种操作:
1 l r c 区间[l,r]中的每个桶中都放入一个颜色为c的球 (1≤l,r ≤n,l≤r,0≤c≤60)
2 l r 查询区间[l,r]的桶中有多少种不同颜色的球 (1≤l,r ≤n,l≤r)
用long long的不同位来表示不同颜色。区间合并用’|’(或)即可,update区间时就用 1<<c 的值来update.
传送门1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAX_N=1e5+5;
ll tree[MAX_N<<2];
ll tag[MAX_N<<2];
ll N,M;
ll lc(ll x) {return x<<1;}
ll rc(ll x) {return x<<1|1;}
int getans(ll x)
{
int ans=0;
while(x)
{
ans+=x&1;
x>>=1;
}
return ans;
}
void push_up(ll p)
{
tree[p]=tree[lc(p)]|tree[rc(p)];
}
void fun(ll p,ll l,ll r,ll k)
{
tag[p]=tag[p]|k;
tree[p]=tree[p]|k;
}
void push_down(ll p,ll l,ll r)
{
ll mid=(l+r)>>1;
fun(lc(p),l,mid,tag[p]);
fun(rc(p),mid+1,r,tag[p]);
tag[p]=0;
}
ll query(ll nl,ll nr,ll p,ll l,ll r)
{
ll res=0;
if(nl<=l&&r<=nr) return tree[p];
if(tag[p]!=0) push_down(p,l,r);
ll mid=(l+r)>>1;
if(nl<=mid)res=res|query(nl,nr,lc(p),l,mid);
if(nr>mid) res=res|query(nl,nr,rc(p),mid+1,r);
return res;
}
void update(ll nl,ll nr,ll p,ll l,ll r,ll k)
{
if(nl<=l&&r<=nr)
{
tag[p]=tag[p]|k;
tree[p]=tree[p]|k;
return;
}
if(tag[p]!=0) push_down(p,l,r);
ll mid=(l+r)>>1;
if(nl<=mid)update(nl,nr,lc(p),l,mid,k);
if(nr>mid)update(nl,nr,rc(p),mid+1,r,k);
push_up(p);
}
int main() {
while(scanf("%lld%lld",&N,&M)!=EOF)
{
memset(tree,0,sizeof(tree));
memset(tag,0,sizeof(tag));
while(M--)
{
ll b;
scanf("%lld",&b);
if(b==1)
{
ll x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
ll temp=pow(2,z);
update(x,y,1,1,N,temp);
}
else
{
ll x,y;
scanf("%lld%lld",&x,&y);
printf("%d\n",getans(query(x,y,1,1,N)));
}
}
}
return 0;
}