线段树 - 状态压缩

链接: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)

输入描述:

有多组数据,对于每组数据:
第一行有两个整数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\n", fun());
            }   
        } 
    }
    return 0;
}

 

posted @ 2018-05-01 08:08  楼主好菜啊  阅读(145)  评论(0编辑  收藏  举报