现在的位置: 首页 > 综合 > 正文

hdu 5023 A Corrupt Mayor’s Performance Art 2014 ACM/ICPC Asia Regional Guangzhou Online

2018年04月25日 ⁄ 综合 ⁄ 共 2310字 ⁄ 字号 评论关闭

人生中第一次写线段树,想想还有点小激动=.=

其实开始照着一份代码敲本地就RE了。。然后一怒之下copy模板:数据结构---各种树模板 持续更新···

关于pushDown的问题想了好久,其实就是父节点的值改变了,要更新其子节点,因为子节点的区间并起来就是父节点表示的区间,这一篇blog写的比较详细:一步一步理解线段树

这一题就是用二进制数表示染了哪一种颜色,query的时候,因为分别对左右子数递归,因此返回值取 或 运算就可以了,最后再用位运算判断一下哪几位是1。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include <ctype.h>
using namespace std;

//hdu 5023
const int maxn=1000100;
int N;
int Q;
#define lson l , mid , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define LL int

/* Node Begin */
LL add[maxn<<2];
LL sum[maxn<<2];
/* Node End */

void PushUp(int rt) {
    sum[rt] = sum[rt<<1] | sum[rt<<1|1];
    //原先的模板求的是区间和,所以是sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    //此处是求区间内一共多少种颜色,所以是 或 的关系
}
void PushDown(int rt,int m) {
    if (add[rt]) {
        add[rt<<1] = add[rt];
        //上一层为[a,c],下一层为[a,b][b+1,c],当上一层延迟标记为x时,下一层对应的儿子的标记也会变成x(因为[a,b]+[b+1,c]=[a,c])
        add[rt<<1|1] = add[rt];
        sum[rt<<1] = sum[rt] ;
        sum[rt<<1|1] = sum[rt];
        //上一层[a,c]被染成y,则下一层对应的子区间颜色也变成了y
      //  sum[rt<<1] = add[rt] ; //all is ok,因为染色时add[i]和sum[i]的赋值相同
      //  sum[rt<<1|1] = add[rt];
        add[rt] = 0;
//        原先的模板如下,是因为之前求的是区间和,父节点的值改变后要再更新子节点。
//        因为子节点可能被多次延迟标记又没有向下传递 ,所以是 “+=”
//        add[rt<<1] += add[rt];
//        add[rt<<1|1] += add[rt];
//        sum[rt<<1] += add[rt] * (m - (m >> 1));
//        sum[rt<<1|1] += add[rt] * (m >> 1);
    }
}
void build(int l,int r,int rt) {
    add[rt] = 0;
    if (l == r) {
        sum[rt]=2;
        return ;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt) {
    if (L <= l && r <= R) {
        add[rt] =1<<(c-1);
        sum[rt] =1<<(c-1);
        //求区间和时,sum如果为非叶子节点,增加量则为c*区间的节点数
        //add[rt] += c;
        //sum[rt] += (LL)c * (r - l + 1);
        return ;
    }
    PushDown(rt , r - l + 1);
    int mid = (l + r) >> 1;
    if (L <= mid) update(L , R , c , lson);
    if (mid < R) update(L , R , c , rson);
    PushUp(rt);
}
LL query(int L,int R,int l,int r,int rt) {
    if (L <= l && r <= R) {
        return sum[rt];
    }
    PushDown(rt , r - l + 1);
    int mid = (l + r) >> 1;
    LL ret = 0;
    if (L <= mid) ret |= query(L , R , lson);
    if (mid < R) ret |= query(L , R , rson);
    //如果是求区间和,则是ret += query(L , R , lson);  此处是颜色种类数,是或的关系
    return ret;
}
int main()
{
    freopen("input.txt","r",stdin);
   // freopen("data.txt","r",stdin);
   // freopen("out1.txt","w",stdout);
    int a,b,c=0;
    while(true)
    {
        scanf("%d %d",&N,&Q);
        if(N==0&&Q==0) break;
        build(1,N,1);
        while(Q--)
        {
            char s[2];
            scanf("%s",&s);
            if(s[0]=='P')
            {
                scanf("%d %d %d",&a,&b,&c);
                update(a,b,c,1,N,1);
            }
            else if(s[0]=='Q')
            {
                scanf("%d %d",&a,&b);
                int ans=query(a,b,1,N,1);
                int flg=1;
                for(int i=0;i<31;i++)
                {
                    int x=ans&(1<<i);
                    if(x)
                    {
                        if(flg)
                        {
                            printf("%d",i+1);
                            flg=0;
                        }
                        else printf(" %d",i+1);
                    }
                }
                printf("\n");
            }
        }
    }
    return 0;
}

抱歉!评论已关闭.