统计颜色 线段树(状态压缩)

链接:https://www.nowcoder.com/acm/contest/105/H
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

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

解题思路:longlong 有63位 每一个节点我们用一个longlong 类型的数字记录是否有该球(按位或),区间满足按位或,

这样每个节点就不用开一个数组来记录球的种类个数,并且区间合并也更快了。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define N 100005
struct node
{
    LL cnt;
    LL sum;
}t[N*4];

void push_up(int rt)
{
    t[rt].sum = t[rt<<1].sum|t[rt<<1|1].sum;
}

void push_down(int rt)
{
    if(t[rt].cnt)
    {
        LL tmp=t[rt].cnt;
        t[rt<<1].cnt |= tmp;
        t[rt<<1|1].cnt |= tmp;
        t[rt<<1].sum |= tmp;
        t[rt<<1|1].sum |= tmp;
        t[rt].cnt=0;
    }
}
void add(int rt,int l,int r,int ql,int qr,LL k)
{
    if(l>=ql && r<=qr)
    {
        t[rt].cnt|=k;
        t[rt].sum|=k;
        return ;
    }
    push_down(rt);
    int m=(l+r)>>1;
    if(ql<=m) add(rt<<1,l,m,ql,qr,k);
    if(qr>m) add(rt<<1|1,m+1,r,ql,qr,k);
    push_up(rt);
}

LL query(int rt,int l,int r,int ql,int qr)
{
    if(l>=ql && r<=qr)
    {
        return t[rt].sum;
    }
    push_down(rt);
    int m=(l+r)>>1;
    LL ans=0;
    if(ql<=m) ans|=query(rt<<1,l,m,ql,qr);
    if(qr>m) ans|=query(rt<<1|1,m+1,r,ql,qr);
    return ans;
}
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        memset(t,0,sizeof(t));
        int f,x,y,c;
        for(int i=0;i<m;i++)
        {
            scanf("%d",&f);
            if(f==1)
            {
                scanf("%d%d%d",&x,&y,&c);
                add(1,1,n,x,y,(1LL<<c));
            }
            if(f==2)
            {
                scanf("%d%d",&x,&y);
                LL ans=query(1,1,n,x,y);
                int s=0;
                while(ans)
                {
                    if(ans&1)s++;
                    ans>>=1;
                }
                printf("%d\n",s);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/82013272