首页 > 其他 > 详细

Count Color 线段树

时间:2019-03-07 14:30:15      阅读:131      评论:0      收藏:0      [点我收藏+]

 

 题意:
 10     给定一个长度为N(N <= 100000)的数列Si,紧接着Q(Q <= 100000)条操作,操作
 11 形式有两种:
 12 1. "C A B C" 将A到B的数都染成C这种颜色。 
 13 2. "P A B" 输出A和B之间不同颜色的数目。


不知道为什么把down写成 just a hook 那题一样就会错
#include<cstdio>
#include<algorithm>
using namespace std;

//input
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define LL long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define N 200005
#define lson L,m,pos<<1
#define rson m+1,R,pos<<1|1

int t[N<<2];
int c[N<<2];

void up(int pos)
{
    t[pos]=(t[pos<<1]|t[pos<<1|1]);
}


void down(int pos,int m)
{
    if(c[pos])
    {
        c[pos<<1]=c[pos<<1|1]=c[pos];
        //t[pos<<1]=c[pos]*(m-(m>>1) );
        //t[pos<<1|1]=(m>>1)*c[pos];
        t[pos<<1]=t[pos<<1|1]=t[pos];
        c[pos]=0;
    }
}

void build(int L,int R ,int pos)
{
    c[pos]=0;

    if(L==R)
    {
       t[pos]=1;
       return ;
    }
    int m=(L+R)>>1;
    build(lson);
    build(rson);
    up(pos);
}

void update(int l,int r,int v,int L,int R,int pos)
{
    if(l<=L&&r>=R)
    {
        t[pos]=v;
        c[pos]=1;
        return ;
    }
    down(pos,R-L+1);
    int m=(L+R)>>1;
    if(l<=m)
        update(l,r,v,lson);
    if(r>m)
        update(l,r,v,rson);
    up(pos);
}

int query(int l,int r,int L,int R,int pos)
{
    int ans=0;
    if(l<=L&&r>=R)
        return t[pos];
    down(pos,R-L+1);
    int m=(L+R)>>1;
    if(r<=m)ans|=query(l,r,lson);
    else if(l>m) ans|=query(l,r,rson);
    else  ans|=query(l,r,lson)|query(l,r,rson);
    return ans;
}

int main()
{
    int n,t,m;

    while(RIII(n,t,m)==3)
    {
    build(1,n,1);
    char str[5];
    int a,b,c;
    while(m--)
    {
        RS(str);
        if(str[0]==C)
        {
            RIII(a,b,c);
            update(a,b,1<<(c-1),1,n,1);
        }
        else
        {
            RII(a,b);
            if(a>b)swap(a,b);
            int temp=query(a,b,1,n,1);
            int ans=0;
            while(temp)
            {
                if(temp%2)
                    ans++;
                temp=(temp>>1);
            }
            printf("%d\n",ans);
        }
     }
    }
}

 

 

附上另一种较好的代码   对懒惰标记的理解更深一步了‘

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
#define ll long long
#define CL(a,b) memset(a,b,sizeof(a))
#define MAXN 100010
 
struct node
{
    int l,r,s;
} t[MAXN<<2];
int L,O,T;
int sum[33];//因为颜色数不多,可以用一个数组来装;1表示该区间有该颜色,0反之
 
void build(int l, int r, int i)
{
    t[i].l = l;
    t[i].r = r;
    t[i].s = 1;
    if(l == r) return ;
    int mid = (l+r)>>1;
    build(l, mid, i<<1);
    build(mid+1, r, i<<1|1);
}
 
void update(int l, int r, int m, int i)
{
    if(t[i].s == m) return ;
    if(t[i].l == l && t[i].r == r)
    {
        t[i].s = m;
        return ;
    }
    if(t[i].s != -1)
    {
        t[i<<1].s = t[i<<1|1].s = t[i].s;
        t[i].s = -1;
    }
    int mid = (t[i].l+t[i].r)>>1;
    if(l > mid) update(l, r, m, i<<1|1);
    else if(r <= mid) update(l, r, m, i<<1);
    else
    {
        update(l, mid, m, i<<1);
        update(mid+1, r, m, i<<1|1);
    }
}
 
void query(int l, int r, int i)
{
    if(t[i].s != -1)//如果纯色把该颜色标记
    {
        sum[t[i].s] = 1;
        return ;
    }
    else//否则继续查询子节点
    {
        int mid = (t[i].l+t[i].r)>>1;
        if(l > mid) query(l, r, i<<1|1);
        else if(r <= mid) query(l, r, i<<1);
        else
        {
            query(l, mid, i<<1);
            query(mid+1, r, i<<1|1);
        }
    }
}
 
int main()
{
    char ch;
    int a,b,c;
    while(scanf("%d%d%d",&L,&T,&O)==3)
    {
        build(1, L, 1);
        while(O--)
        {
            getchar();
            scanf("%c",&ch);
            if(ch == C)
            {
                scanf("%d%d%d",&a,&b,&c);
                update(a, b, c, 1);
            }
            int ans = 0;
            if(ch == P)
            {
                CL(sum, 0);//每次查询之前清零
                scanf("%d%d",&a,&b);
                query(a, b, 1);
                for(int i=1; i<=T; i++)//统计出现过的颜色数
                    if(sum[i]) ans++;
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}

 

Count Color 线段树

原文:https://www.cnblogs.com/bxd123/p/10489213.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!