codeforces 482B. Interesting Array【线段树区间更新】

题目:codeforces 482B. Interesting Array

题意:给你一个值n和m中操作,每种操作就是三个数 l ,r,val。就是区间l---r上的与的值为val,最后问你原来的数组是多少?如果不存在输出no

分析:分析发现要满足所有的区间,而一个点上假如有多个区间的话,这个点的值就是所有区间或的值,因为只有这样才能满足所有区间的,把所有位上的1都保存下来了,那么可以发现用线段树来维护,但是那么怎么判断满不满足条件呢?可以也用线段树,更新了之后在整个维护一遍看看满不满足题意,如果满足的话就可以了。

AC代码:

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 110000;
struct Node
{
    int l,r;
    int val;
};
Node tree[10*N];
void build(int o,int l,int r)
{
    tree[o].l = l,tree[o].r = r;
    tree[o].val = 0;
    if(l==r)
        return ;
    int mid = (l+r)/2;
    build(o+o,l,mid);
    build(o+o+1,mid+1,r);
}
void update(int o,int l,int r,int val)
{
    if(tree[o].l==l && tree[o].r==r)
    {
        tree[o].val|=val;
        return ;
    }
    int mid = (tree[o].l + tree[o].r)/2;
    if(mid>=r)
        update(o+o,l,r,val);
    else if(l>mid)
        update(o+o+1,l,r,val);
    else
    {
        update(o+o,l,mid,val);
        update(o+o+1,mid+1,r,val);
    }
}
int query(int o,int l,int r)
{
    if(tree[o].l==l && tree[o].r==r)
        return tree[o].val;
    int mid = (tree[o].l + tree[o].r)/2;
    if(mid>=r)
        return query(o+o,l,r);
    else if(l>mid)
        return query(o+o+1,l,r);
    else
    {
        return query(o+o,l,mid)&query(o+o+1,mid+1,r);
    }
}
vector<int> ans;
void solve(int o)
{
    if(o!=1)
        tree[o].val |= tree[o/2].val;
    //printf("%d %d %d %d\n",o,tree[o].l,tree[o].r,tree[o].val);
    if(tree[o].l==tree[o].r){
        ans.push_back(tree[o].val);
        return ;
    }
    solve(o+o);
    solve(o+o+1);
}
Node a[N];
int main()
{
    //freopen("Input.txt","r",stdin);
    int n,m;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].val);
        update(1,a[i].l,a[i].r,a[i].val);
    }
    int ok=1;
    for(int i=0;i<m;i++)
    {
        if(query(1,a[i].l,a[i].r)!=a[i].val)
        {
            ok=0;
            break;
        }
    }
    solve(1);
    if(ok){
        puts("YES");
        for(int i=0;i<ans.size();i++)
            printf("%d%c",ans[i],i==n?'\n':' ');
        ans.clear();
    }
    else
        puts("NO");
    return 0;
}
时间: 2024-08-26 03:16:29

codeforces 482B. Interesting Array【线段树区间更新】的相关文章

Codeforces 482B Interesting Array(线段树)

题目链接:Codeforces 482B Interesting Array 题目大意:给定一个长度为N的数组,现在有M个限制,每个限制有l,r,q,表示从a[l]~a[r]取且后的数一定为q,问是 否有满足的数列. 解题思路:线段树维护,每条限制等于是对l~r之间的数或上q(取且的性质,相应二进制位一定为1),那么处理完所有的 限制,在进行查询,查询对应每个l~r之间的数取且是否还等于q.所以用线段树维护取且和,修改为或操作. #include <cstdio> #include <c

CF#52 C Circular RMQ (线段树区间更新)

Description You are given circular array a0,?a1,?...,?an?-?1. There are two types of operations with it: inc(lf,?rg,?v) - this operation increases each element on the segment [lf,?rg] (inclusively) by v; rmq(lf,?rg) - this operation returns minimal v

HDU 1689 Just a Hook 线段树区间更新求和

点击打开链接 Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 18894    Accepted Submission(s): 9483 Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include

HDU 5023 A Corrupt Mayor&#39;s Performance Art 线段树区间更新+状态压缩

Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5023 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <string> 7 #include <cmath> 8 using namesp

hihocoder 1080 线段树(区间更新)

题目链接:http://hihocoder.com/problemset/problem/1080 , 两种操作的线段树(区间更新). 这道题前一段时间一直卡着我,当时也是基础不扎实做不出来,今天又想了想其实还是比较简单的,也只能怪自己太弱了. 这道题坑就坑在是有两个操作:set和add,所以lazy标记数组就需要两个,但是有一点要考虑的是一个区间上set与add的先后关系——如果对于一个区间set和add标记同时存在,那么应该如果处理:一种情况set在add之前,那么就按照正常顺序来就可以了:

(简单) POJ 3468 A Simple Problem with Integers , 线段树+区间更新。

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. 题意

HDU 5023 A Corrupt Mayor&#39;s Performance Art(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色,有两种操作: P a b c  把区间a到b涂成c颜色 Q a b 查询区间a到b的颜色 线段树区间更新,每个节点保存的信息有,存储颜色的c,30种颜色可以压缩到一个int型里面存储,然后还有一个tot,表示这个区间一共有多少种颜色. 对于P操作,依次往下寻找,找要更新的区间,找到要更新的区间之前