HDU 5023 A Corrupt Mayor's Performance Art (线段树 位运算)

来源:互联网 发布:惠惠助手淘宝不显示 编辑:程序博客网 时间:2024/06/04 19:30

题意:长度为n的数组,每个点的颜色开始都是2,然后q次操作,操作1是把[L,R] 区间的颜色变成某个值C, 第二种是查询[L,R] 区间存在哪些颜色,并把颜色的编号输出( 按照字典序).(N<=1e6, M<=1e5, C<=30)


思路:因为C<=30,所以我们可以把颜色用二进制来吃存储,线段树每个节点的二进制表示其区间存在的颜色。这样就成了简单的区间更新和查询了。


代码:

#include<bits/stdc++.h>using namespace std;const int maxn = 1e6+5;int tree[maxn*4], lazy[maxn*4];int n, m;void push_up(int root){    tree[root] = tree[root*2] | tree[root*2+1];}void push_down(int root, int l, int r){    if(lazy[root])    {        tree[root*2] = tree[root*2+1] = 1<<(lazy[root]-1);        lazy[root*2] = lazy[root*2+1] = lazy[root];        lazy[root] = 0;    }}void build(int root, int l, int r){    if(l == r)    {        tree[root] = 2;        lazy[root] = 0;        return ;    }    int mid = (l+r)/2;    build(root*2, l, mid);    build(root*2+1, mid+1, r);    push_up(root);}void update(int root, int l, int r, int i, int j, int val){    if(i <= l && j >= r)    {        tree[root] = 1<<(val-1);        lazy[root] = val;        return ;    }    push_down(root, l, r);    int mid = (l+r)/2;    if(i <= mid) update(root*2, l, mid, i, j, val);    if(j > mid) update(root*2+1, mid+1, r, i, j, val);    push_up(root);}int query(int root, int l, int r, int i, int j){    if(i <= l && j >= r) return tree[root];    push_down(root, l, r);    int tmp = 0;    int mid = (l+r)/2;    if(i <= mid) tmp |= query(root*2, l, mid, i, j);    if(j > mid) tmp |= query(root*2+1, mid+1, r, i, j);    return tmp;}int main(void){    while(cin >> n >> m)    {        if(n == 0 && m == 0) break;        memset(lazy, 0, sizeof(lazy));        memset(tree, 0, sizeof(tree));        build(1, 1, n);        for(int i = 1; i <= m; i++)        {            char cmd;            int x, y, z;            scanf(" %c %d%d", &cmd, &x, &y);            if(cmd == 'P')            {                scanf("%d", &z);                update(1, 1, n, x, y, z);            }            else            {                int ans = query(1, 1, n, x, y);                int flag = 0;                for(int i = 1; i <= 30; i++)                {                    if(ans&(1<<(i-1)))                    {                        if(flag) printf(" ");                        printf("%d", i);                        flag++;                    }                }                puts("");            }        }    }    return 0;}


阅读全文
1 0
原创粉丝点击