HDU 5023 线段树+状压

2014
ACM/ICPC Asia Regional Guangzhou Online

N个节点,M个操作。

P操作把l-r全部改为x (1<=x<=30)

Q操作询问l-r出现的数字,升序输出

线段树成端更新+成端查找

因为X最大30,用二进制压缩存储已经出现的数字。

#include "stdio.h"
#include "string.h"

struct node
{
    int l,r;
    __int64 x,lazy;
}data[4001000];
__int64 ans;
__int64 b[40];

void Pushdown(int k)
{
    if (data[k].l==data[k].r) return ;
    if (data[k].lazy==0) return ;

    data[k*2].lazy=data[k*2].x=data[k].lazy;
    data[k*2+1].lazy=data[k*2+1].x=data[k].lazy;
    data[k].lazy=0;

}
void build(int l,int r,int k)
{
    int mid;
    data[k].l=l;
    data[k].r=r;
    data[k].lazy=0;
    data[k].x=2;

    if (l==r) return ;

    mid=(l+r)/2;
    build(l,mid,k*2);
    build(mid+1,r,k*2+1);
}

void updata(int l,int r,int k,int op)
{
    int mid;
    if (data[k].l==l && data[k].r==r)
    {
        data[k].lazy=b[op];
        data[k].x=b[op];
        return ;
    }

    Pushdown(k);
    mid=(data[k].l+data[k].r)/2;

    if (r<=mid) updata(l,r,k*2,op);
    else
        if (l>mid) updata(l,r,k*2+1,op);
    else
    {
        updata(l,mid,k*2,op);
        updata(mid+1,r,k*2+1,op);
    }

    if (data[k*2].x==data[k*2+1].x) data[k].x=data[k*2].x;
    else data[k].x=-1;
}

void query(int l,int r,int k)
{
    int mid;
    if (data[k].x!=-1)
    {
        ans|=data[k].x;
        return;
    }

    mid=(data[k].l+data[k].r)/2;
    Pushdown(k);

    if (r<=mid) query(l,r,k*2);
    else
        if (l>mid) query(l,r,k*2+1);
    else
    {
        query(l,mid,k*2);
        query(mid+1,r,k*2+1);
    }
}

void pri()
{
    int first,i,x;

    first=1;
    for (i=1;i<=30;i++)
    {
        x=ans%2;
        if (x==1)
        {
            if (first==0) printf(" ");
            first=0;
            printf("%d",i);
        }
        ans/=2;
    }
    printf("\n");

}
int main()
{
    int n,m,l,i,r,x;
    char op;
    b[1]=1;
    for (i=2;i<=30;i++)
        b[i]=b[i-1]*2;

    while (scanf("%d%d",&n,&m)!=EOF)
    {
        if (n==0 && m==0) break;
        build(1,n,1);
        while (m--)
        {
            getchar();
            scanf("%c%d%d",&op,&l,&r);
            if (op=='P')
            {
                scanf("%d",&x);
                updata(l,r,1,x);
            }
            else
            {
                ans=0;
                query(l,r,1);
                pri();
            }
        }
    }
    return 0;
}
时间: 2024-10-01 10:59:14

HDU 5023 线段树+状压的相关文章

hdu 5023 线段树 区间 2014广东区域赛网赛

http://acm.hdu.edu.cn/showproblem.php?pid=5023 当时大一学弟15minAC 搞得我压力山大 给队友写了 今天重新做了下,题还是很水  但是因为pushdown的时候if(l==r)return没有写  WA了一次 感觉到现在,简单的线段树已经可以随意点写了,就是按照自己的理解写,别慌,错了按树的结构思考下重新写 查询不知道pushdown所有的会不会超时,我的还是区间的查询,凡是子区间被修改过的结点,该节点pushdown后 其co值都被我改为0 然

hdu 5023 线段树延迟更新+状态压缩

/* 线段树延迟更新+状态压缩 */ #include<stdio.h> #define N 1100000 struct node { int x,y,yanchi,sum; }a[N*4]; int lower[31]; void build(int t,int x,int y) { a[t].x=x; a[t].y=y; a[t].yanchi=0; if(x==y){ a[t].sum=lower[1]; return ; } int temp=t<<1; int mid=

HDU 5023线段树区间染色,统计区间内颜色个数

这个也是一个线段树的模板 #include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> #include<set> using namespace std; const int maxx = 1000050; set<int>s; struct node{ int color; int left; int right; int mid; }a[m

HDU_3071 Gcd &amp; Lcm game 【素数分解 + 线段树 + 状压】

一.题目  Gcd & Lcm game 二.分析 非常好的一题. 首先考虑比较暴力的做法,肯定要按区间进行处理,对于$lcm$和$gcd$可以用标准的公式进行求,但是求$lcm$的时候是肯定会爆$long long$的. 考虑用素数分解,将所有的数分解后,发现素因子的个数有限,且每个因子的幂也有限,最多的也就是$2^_6$,然后可以考虑将素因子用二进制的每一位进行表示.对于$2,3,5,7$可能会要的多点,所以多给给几位就可以了,最后发现,刚好可以$32$位以内. 这里就需要写两个转换函数,然

HDU 1394(线段树单点更新)

题意:就是给出一串数,当依次在将第一个数变为最后一个数的过程中,要你求它的最小逆序数. 思路:可以用树状数组和线段数做.这里我是用线段树做的.建的是一棵空树,然后每插入一个点之前,统计大于这个数的有多少个,直到所有的数都插入完成,就结果了逆序树的统计. 要得出答案主要是利用了一个结论,如果是0到n的排列,那么如果把第一个数放到最后,对于这个数列,逆序数是减少a[i],而增加n-1-a[i]的. #include<iostream> #include<cstring> #includ

HDU 4893 线段树裸题

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2512    Accepted Submission(s): 751 Problem Description Recently, Doge got a funny birthday present from his new friend, Pro

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw

HDU 4924 Football Manager(状压DP)

题目连接 : http://acm.hdu.edu.cn/showproblem.php?pid=4924 题意 : n(<=20)个人选出11个人作为首发组成a-b-c阵容,每个人都有自己擅长的位置,并且每个人和其他人会有单向的厌恶和喜欢关系,每个人对于自己擅长的位置都有两个值CA和PA,有喜欢或者厌恶关系的两个人在一起也会影响整个首发的CA总值,要求选出一套阵容使得CA最大,或者CA一样的情况下PA最大. 思路 : 状压搞,dp[s]s的二进制表示20个人中选了那几个人,然后规定选进来的顺序

hdu 4893 线段树 --- 也是两个变 类似双标记

http://acm.hdu.edu.cn/showproblem.php?pid=4893 开始的时候,我按双标记,WA了一下午,搞不定,我是用的两个标记add--表示当前结点中有值发生变化,flag,斐波那契的懒惰标记,但是估计是我自己处理的有问题,一直不对 参考了别人的代码,写法还是很不错的,Add变量维护的是,完全变成Fibonacci的时候的和,---回头我再重新写一遍 #include <cstdio> #include <cstring> #include <a