一道线段树染色,但是这里是桶,我犯了经验主义以为是覆盖问题
数据不大,用二进制表示即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<algorithm> #include<stack> #include<vector> #include<cstring> using namespace std; typedef long long ll; const int N=1e5+10; const int mod=1e9+7; int n,m; struct node{ int l,r; ll cnt; ll lazy; }tr[N<<2]; void build(int u,int l,int r){ if(l==r){ tr[u]={l,r,0,0}; return ; } else{ tr[u]={l,r,0,0}; int mid=l+r>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); } } void pushdown(int u){ tr[u<<1].cnt|=tr[u].lazy; tr[u<<1|1].cnt|=tr[u].lazy; tr[u<<1].lazy|=tr[u].lazy; tr[u<<1|1].lazy|=tr[u].lazy; tr[u].lazy=0; } void pushup(int u){ tr[u].cnt=tr[u<<1].cnt|tr[u<<1|1].cnt; } void modify(int u,int l,int r,int c){ if(tr[u].l>=l&&tr[u].r<=r){ tr[u].cnt|=(1ll<<c); tr[u].lazy|=(1ll<<c); return ; } if(tr[u].lazy) pushdown(u); int mid=tr[u].l+tr[u].r>>1; if(l<=mid) modify(u<<1,l,r,c); if(r>mid) modify(u<<1|1,l,r,c); pushup(u); } ll query(int u,int l,int r){ if(tr[u].l>=l&&tr[u].r<=r) return tr[u].cnt; if(tr[u].lazy) pushdown(u); int mid=tr[u].l+tr[u].r>>1; ll res=0; if(l<=mid) res=query(u<<1,l,r); if(r>mid) res|=query(u<<1|1,l,r); return res; } int check(ll x){ int res=0; while(x){ if(x&1) res++; x>>=1; } return res; } int main(){ while(cin>>n>>m){ int i; build(1,1,n); for(i=1;i<=m;i++){ int type; scanf("%d",&type); if(type==1){ int l,r,c; scanf("%d%d%d",&l,&r,&c); modify(1,l,r,c); } else{ int l,r; scanf("%d%d",&l,&r); printf("%d ",check(query(1,l,r))); } } } }