题目链接:https://www.nowcoder.com/acm/contest/105/H
题目描述
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)
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)
输入描述:
有多组数据,对于每组数据: 第一行有两个整数n,m(1≤n,m≤100000) 接下来m行,代表m个操作,格式如题目所示。
输出描述:
对于每个2号操作,输出一个整数,表示查询的结果。
示例1
输入
10 10 1 1 2 0 1 3 4 1 2 1 4 1 5 6 2 2 1 6 1 7 8 1 2 3 8 1 8 10 3 2 1 10 2 3 8
输出
2 3 2 4 3
基本的线段树应用,区间更新,区间求和。
重点在于在线跟新时lazy_tag的处理,对更新的更新需要累加,而不是直接把父节点的值复制过来。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 100005
#define INF 100
using namespace std;
long long seg[MAXN<<2]; // seg[i]64位 每一位代表一种颜色
long long flg[MAXN<<2];
int seg_n;
void init( int _n ) {
seg_n = 1;
memset( seg, 0, sizeof(seg) );
memset( flg, 0, sizeof(flg) );
while ( seg_n < _n ) seg_n<<=1;
}
// 强烈要求注意这里的lazy_tag更新方式
// 在这里错了无数发提交
// 将父节点的更新值 累加到当前节点 而不是简单的复制过来
void pushdown( int l, int r, int k ) {
if ( r-l == 1 ) return ;
flg[2*k+1] |= flg[k];
seg[2*k+1] |= flg[k];
flg[2*k+2] |= flg[k];
seg[2*k+2] |= flg[k];
flg[k] = 0;
}
void pushup( int k ) {
seg[k] = seg[2*k+1] | seg[2*k+2];
}
void update( int l, int r, int a, int b, int k, int c ) {
if ( l >= b || r <= a ) return;
if ( a <= l && b >= r ) {
// 当心数字溢出
seg[k] |= (1LL<<c);
flg[k] |= (1LL<<c);
return ;
}
if ( flg[k] ) pushdown(l, r, k);
update( l, (l+r)>>1, a, b, 2*k+1, c );
update( (l+r)>>1, r, a, b, 2*k+2, c );
pushup(k);
}
long long query( int l, int r, int a, int b, int k ) {
if ( l >= b || r <= a ) return 0;
if ( a <= l && b >= r ) return seg[k];
if ( flg[k] ) pushdown(l, r, k);
return query(l, (l+r)>>1, a, b, 2*k+1) | query((l+r)>>1, r, a, b, 2*k+2);
}
int tran( long long ans ) {
int res = 0;
while ( ans > 0 ) {
res ++;
ans &= ans-1;
}
return res;
}
int main()
{
int n, m;
int op, l, r, c;
long long ans;
while ( scanf( "%d%d", &n, &m ) != EOF ) {
init( n );
for ( int i = 0 ; i < m ; ++ i ) {
scanf( "%d", &op );
if ( op == 1 ) {
scanf( "%d%d%d", &l, &r, &c );
update( 0, seg_n, l-1, r, 0, c );
} else {
scanf( "%d%d", &l, &r );
ans = query( 0, seg_n, l-1, r, 0 );
printf( "%d\n", tran(ans) );
}
}
}
return 0;
}