NC15667 统计颜色(线段树染色)

一道线段树染色,但是这里是桶,我犯了经验主义以为是覆盖问题

数据不大,用二进制表示即可

#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\n",check(query(1,l,r)));
            }
        }
     }
}

原文地址:https://www.cnblogs.com/ctyakwf/p/12588110.html

时间: 2024-08-03 12:48:33

NC15667 统计颜色(线段树染色)的相关文章

ZOJ1610 Count the Colors 经典线段树染色问题

题意,给你n个  x,y,c,意思就是区间[x,y]被染成C色,但是颜色会被覆盖的,染色操作完成以后 问你每种颜色有多少段 并输出颜色编号id跟段数cnt 经典问题,不过写的有点撮吧,没去看别人的,这个方法应该是最传统的最普通的,常规的开数组记录,也许大神们有更高端的方法 #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring>

POJ2528 Mayor&#39;s posters(线段树染色问题+离散化)

题目大意:有t组数据,每组数据给你n张海报(1<=n<=10000),下面n组数据分别给出每张海报的左右范围(1 <= l <= r <= 10000000),下一张海报会覆盖前一张海报,求最后可见(包括完全和不完全可见)的海报有几张. 例如: 1 5 1 4 2 6 8 10 3 4 7 10 如上图所示,答案为4. 解题思路:其实这是一道区间染色问题,但是由于查找区间太大,显然直接建树会导致MLE,所以这里通过使用对区间的离散化来缩小查找范围.参考了一些大牛博客,简单说一

bzoj 2120: 数颜色 线段树套平衡树

/************************************************************** Problem: 2120 User: wangyucheng Language: C++ Result: Time_Limit_Exceed ****************************************************************/ #include<iostream> #include<cstdio> #incl

pku 2777(经典线段树染色问题)

Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 41202   Accepted: 12458 Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.

贴海报 (线段树染色-离散化

n(n<=10000) 个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000) .求出最后还能看见多少张海报. 虽然之前学过离散化,但用的时候就想不起来 emm: 10000个海报 最多有10000个区间 20000个坐标值,远少于10000000,因此采用离散化 将离散化后的坐标对应数组下标储存到线段树中 : 染色区间是整段的,本身就可以看做 lazy标记 ,需要下推函数: 下推 : void push_down(int pos){ if( c

codeforces - 444c DZY Loves Colors(线段树+染色)

C. DZY Loves Colors time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output DZY loves colors, and he enjoys painting. On a colorful day, DZY gets a colorful ribbon, which consists of n units (they

P2161 [SHOI2009]会场预约 - 线段树染色

是真的染色,把不同预约看做不同颜色,现在问题就是一个区间内不同颜色的数量,这个分块线段树都能做吧(不考虑复杂度用莫队也行) 注意,线段树的最大边界必须是定值,不能随输入改变(一开始懒得离线动态更新右端点然后节点的编号就串了) 注意数组大小,因为same和tag数组都是针对线段树节点设置的,所以其数组大小也要开4倍 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio

[JXOI2017]颜色 线段树扫描线 + 单调栈

---题面--- 题解: 首先题目要求删除一些颜色,换个说法就是要求保留一些颜色,那么观察到,如果我们设ll[i]和rr[i]分别表示颜色i出现的最左边的那个点和最右边的那个点,那么题目就是在要求我们选出的区间要满足区间[l, r]内所有颜色的max(rr[i]) <= r,并且min(ll[i]) >= l. 因为是区间相关的问题,又涉及到左右端点,因此我们考虑扫描线,那么考虑如何维护它. 因为每个颜色的ll[i]和rr[i]可以看做构成了一个区间,那么现在已经进入线段树的节点就分2种情况.

BZOJ3688折线统计 dp+线段树

Description 二 维平面上有n个点(xi, yi),现在这些点中取若干点构成一个集合S,对它们按照x坐标排序,顺次连接,将会构成一些连续上升.下降的折线,设其数量为f(S).如下图 中,1->2,2->3,3->5,5->6(数字为下图中从左到右的点编号),将折线分为了4部分,每部分连续上升.下降.   现给定k,求满足f(S) = k的S集合个数. Input 第一行两个整数n和k,以下n行每行两个数(xi, yi)表示第i个点的坐标.所有点的坐标值都在[1, 1000