• poj-2777(区间线段树,求种类数模板)


    题目链接:http://poj.org/problem?id=2777

    参考文章:https://blog.csdn.net/heucodesong/article/details/81038360

    题目大意:给出T中颜色,可以给一段区域涂色,初始是全为1的颜色,然后有两种操作

    (1)C x y z表示将区间x到y的颜色更改为z

    (2)P x y 表示查询区间x到y的颜色种类。

    题目看起来不符合区间和的条件,但是可以通过二进制转化一下。

    初始化肯定都是颜色1,就表示只有一种颜色,然后每次更新颜色时,取这个数的a[x]=1<<(Item-1),a[x]中的1的位置就表示每个颜色的位置

    然后pushup操作就改为:a[x]=a[x*2]|a[x*2+1],a[x]中的1的个数就是这个区间颜色的个数。对于Item为什么要-1,其实就是初始颜色时1,就相当于从第0位开始,与数组的0-n-1类似。

    (易错:我当时在查询函数中一直出错,但我还没发现,主要是考虑ans1,ans2,ans的初始值是0,这里我已开始写成了1,就错了,

    还有ans=ans1|ans2这一步不能少,不然编译会出错,总之,先求出结果再返回。)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    const int maxn = 1e5+10;
    int a[maxn*4],b[maxn*4];
    void Init()
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
    }
    void pushup(int x)
    {
        a[x]=a[x*2]|a[x*2+1];
    }
    void pushdown(int x)
    {
        if(b[x])
        {
            a[x*2]=b[x];
            a[x*2+1]=b[x];
            b[x*2]=b[x];
            b[x*2+1]=b[x];
            b[x]=0;
        }
    }
    void build(int x,int l,int r)
    {
        if(l==r)
        {
            a[x]=1;return ;
        }
        int mid=(l+r)/2;
        build(x*2,l,mid);
        build(x*2+1,mid+1,r);
        pushup(x);
    }
    void update(int x,int l,int r,int A,int B,int Item)
    {
        if(A<=l&&r<=B)
        {
            a[x]=1<<(Item-1);
            b[x]=1<<(Item-1);
            return ;
        }
        int mid=(l+r)/2;
        pushdown(x);
        if(A<=mid) update(x*2,l,mid,A,B,Item);
        if(B>mid) update(x*2+1,mid+1,r,A,B,Item);
        pushup(x);
    }
    int query(int x,int l,int r,int A,int B)
    {
        if(A<=l&&r<=B)
        {
            return a[x];
        }
        int mid=(l+r)/2;
        pushdown(x);
        int ans1=0,ans2=0,ans=0;
        if(A<=mid) ans1=query(x*2,l,mid,A,B);
        if(B>mid) ans2=query(x*2+1,mid+1,r,A,B);
        ans=ans1|ans2;
        return ans;
    }
    int main(void)
    {
        int n,m,t,i,x,y,z;
        while(~scanf("%d%d%d",&n,&t,&m))
        {
            Init();
            build(1,1,n);
            char str[10];
            while(m--)
            {
                scanf("%s",str);
                if(str[0]=='C')
                {
                    scanf("%d%d%d",&x,&y,&z);
                    if(x>y)
                    {
                        int tp=x;
                        x=y;
                        y=tp;
                    }
                    update(1,1,n,x,y,z);
                }
                else
                {
                    scanf("%d%d",&x,&y);
                    if(x>y)
                    {
                        int tp=x;
                        x=y;
                        y=tp;
                    }
                    int cnt=0,ans=query(1,1,n,x,y);
                    while(ans)
                    {
                        if(ans&1) cnt++;
                        ans>>=1;
                    }
                    printf("%d
    ",cnt);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    POJ 1222 POJ 1830 POJ 1681 POJ 1753 POJ 3185 高斯消元求解一类开关问题
    POJ 3237 Tree (树链剖分)
    2038: [2009国家集训队]小Z的袜子(hose) (莫队算法)
    HDU 4685 Prince and Princess (2013多校8 1010题 二分匹配+强连通)
    HDU 4678 Mine (2013多校8 1003题 博弈)
    HDU 4679 Terrorist’s destroy (2013多校8 1004题 树形DP)
    HDU 4681 String(2013多校8 1006题 DP)
    1036: [ZJOI2008]树的统计Count (树链剖分)
    HDU 3966 Aragorn's Story (树链剖分+树状数组)
    PHP服务端支付宝支付及回调
  • 原文地址:https://www.cnblogs.com/2018zxy/p/10139990.html
Copyright © 2020-2023  润新知