zoukankan      html  css  js  c++  java
  • Count Color 线段树

     题意:
     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
    ",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
    ",ans);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    第三章
    第二章
    第一章
    第九章 硬件抽象层:HAL
    第十章 嵌入式Linux的调试技术
    第八章 让开发板发出声音:蜂鸣器驱动
    第七章
    第六章
    第五章总结
    第四章 源代码的下载和编译
  • 原文地址:https://www.cnblogs.com/bxd123/p/10489213.html
Copyright © 2011-2022 走看看