链接: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
题意:直接看题目描述就可以
思路分析 : 一个线段树就可以,用二进制状态表示对应的颜色位有没有气球
代码示例:
#define ll long long
const ll maxn = 1e5+5;
const ll mod = 1e9+7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const ll inf = 0x3f3f3f3f;
#define lson k<<1
#define rson k<<1|1
ll n, m;
struct node
{
ll l, r;
ll f;
ll x;
}t[maxn<<2];
void build(ll l, ll r, ll k){
t[k].l = l, t[k].r = r;
t[k].f = 0, t[k].x = 0;
if (l == r) return;
ll m = (l+r)>>1;
build(l, m, lson);
build(m+1, r, rson);
}
void pushdown(ll k){
t[lson].x |= t[k].f;
t[rson].x |= t[k].f;
t[lson].f |= t[k].f;
t[rson].f |= t[k].f;
t[k].f = 0;
}
void pushup(ll k){
t[k].x = t[lson].x|t[rson].x;
}
void update(ll l, ll r, ll c, ll k){
if (l <= t[k].l && t[k].r <= r){
t[k].x |= (1ll<<c);
t[k].f |= (1ll<<c);
return;
}
if (t[k].f) pushdown(k);
ll m = (t[k].l+t[k].r)>>1;
if (l <= m) update(l, r, c, lson);
if (r > m) update(l, r, c, rson);
pushup(k);
}
ll ans;
void query(ll l, ll r, ll k){
if (l <= t[k].l && t[k].r <= r){
ans |= t[k].x;
return;
}
if (t[k].f) pushdown(k);
ll m = (t[k].l + t[k].r)>>1;
if (l <= m) query(l, r, lson);
if (r > m) query(l, r, rson);
}
ll fun(){
ll x = ans;
ll cnt = 0;
while(x){
if (x%2) cnt++;
x /= 2;
}
return cnt;
}
ll pt, l, r, c;
int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
while(~scanf("%lld%lld", &n, &m)){
build(1, n, 1);
for(ll i = 1; i <= m; i++){
scanf("%lld%lld%lld", &pt, &l, &r);
if (pt == 1){
scanf("%lld", &c);
update(l, r, c, 1);
}
else {
ans = 0;
query(l, r, 1);
printf("%lld
", fun());
}
}
}
return 0;
}