题意:长度为n的序列a,每个a[i]都是一个桶,可以放无限个球,m次操作
操作1:向[l,r]内的桶放入一个颜色为c的球.
操作2:询问[l,r]内有多少个不同的数?
n,m<=1e5. 0<=c<=60.
线段树每个节点保存61位的二进制数.其第i位为1,表示[l,r]中有存在颜色i.
涉及到的操作只有:懒标记和区间置位..
操作1:向[l,r]内的桶放入一个颜色为c的球.
操作2:询问[l,r]内有多少个不同的数?
n,m<=1e5. 0<=c<=60.
线段树每个节点保存61位的二进制数.其第i位为1,表示[l,r]中有存在颜色i.
涉及到的操作只有:懒标记和区间置位..
复习:在线段树上定位一个区间的复杂度为O(logn).加上lazy就可以使区间update操作的复杂度也是O(logn)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m;
struct node{
int l,r;
ll add,val;
}t[N<<2];
void push_up(int o)
{
t[o].val=t[o<<1].val|t[o<<1|1].val;
}
void build(int o,int l,int r)
{
t[o].l=l,t[o].r=r;
t[o].add=t[o].val=0;
if(l==r)
return;
int m=l+r>>1;
build(o<<1,l,m);
build(o<<1|1,m+1,r);
push_up(o);
}
void push_down(int o)
{
if(t[o].add)
{
t[o<<1].val|=t[o].add;
t[o<<1|1].val|=t[o].add;
t[o<<1].add|=t[o].add;
t[o<<1|1].add|=t[o].add;
t[o].add=0;
}
}
void update(int o,int ql,int qr,ll val)
{
int l=t[o].l,r=t[o].r;
if(ql<=l&&qr>=r)
{
t[o].val=t[o].val|val;
t[o].add=t[o].add|val;
return;
}
push_down(o);
int m=l+r>>1;
if(ql<=m)
update(o<<1,ql,qr,val);
if(qr>m)
update(o<<1|1,ql,qr,val);
push_up(o);
}
ll query(int o,int ql,int qr)
{
int l=t[o].l,r=t[o].r;
if(ql<=l&&qr>=r)
return t[o].val;
push_down(o);
ll res=0,m=l+r>>1;
if(ql<=m)
res|=query(o<<1,ql,qr);
if(qr>m)
res|=query(o<<1|1,ql,qr);
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>n>>m)
{
build(1,1,n);
int op,l,r;
ll val;
while(m--)
{
cin>>op>>l>>r;
if(op==1)
{
cin>>val;
update(1,l,r,ll(1ll<<val));
}
else
{
ll cnt=0,res=query(1,l,r);
for(int i=0;i<=60;i++)
cnt+=((res>>i)&1);
cout<<cnt<<'\n';
}
}
}
return 0;
}