Codeforces Round #275 Div.1 B Interesting Array --线段树

题意: 构造一个序列,满足m个形如:[l,r,c] 的条件。 [l,r,c]表示[l,r]中的元素按位与(&)的和为c。

解法: 线段树维护,sum[rt]表示要满足到现在为止的条件时该子树的按位与和至少为多少。

更新时,如果val的pos位为1,那么整个区间的按位与和pos位也应该为1,否则与出来就不对了。(这是本题解题的核心)

那么此时更新 sum[rt] |= val 即可。然后再check一遍看是否满足所有条件即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 100007

int sum[4*N],mark[4*N];

void pushup(int rt)
{
    sum[rt] = sum[2*rt]&sum[2*rt+1];
}

void pushdown(int l,int r,int rt)
{
    if(mark[rt])
    {
        mark[2*rt] |= mark[rt];
        mark[2*rt+1] |= mark[rt];
        sum[2*rt] |= mark[rt];
        sum[2*rt+1] |= mark[rt];
        mark[rt] = 0;
    }
}

void build(int l,int r,int rt)
{
    mark[rt] = sum[rt] = 0;
    if(l == r)
        return;
    int mid = (l+r)/2;
    build(l,mid,2*rt);
    build(mid+1,r,2*rt+1);
}

void update(int l,int r,int aa,int bb,int val,int rt)
{
    if(aa <= l && bb >= r)
    {
        sum[rt] |= val;
        mark[rt] |= val;
        return;
    }
    pushdown(l,r,rt);
    int mid = (l+r)/2;
    if(aa <= mid) update(l,mid,aa,bb,val,2*rt);
    if(bb > mid)  update(mid+1,r,aa,bb,val,2*rt+1);
    pushup(rt);
}

int query(int l,int r,int aa,int bb,int rt)
{
    if(aa <= l && bb >= r)
        return sum[rt];
    pushdown(l,r,rt);
    int mid = (l+r)/2;
    if(bb <= mid)     return query(l,mid,aa,bb,2*rt);
    else if(aa > mid) return query(mid+1,r,aa,bb,2*rt+1);
    else              return (query(l,mid,aa,bb,2*rt)&query(mid+1,r,aa,bb,2*rt+1));
}

void print(int l,int r,int rt)
{
    if(l == r)
    {
        printf("%d ",sum[rt]);
        return;
    }
    pushdown(l,r,rt);
    int mid = (l+r)/2;
    print(l,mid,2*rt);
    print(mid+1,r,2*rt+1);
}

struct Q
{
    int l,r,val;
}q[N];

int main()
{
    int n,m,i;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,n,1);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].val);
            update(1,n,q[i].l,q[i].r,q[i].val,1);
        }
        for(i=1;i<=m;i++)
        {
            if(query(1,n,q[i].l,q[i].r,1) != q[i].val)
                break;
        }
        if(i == m+1)
            puts("YES"),print(1,n,1),puts("");
        else
            puts("NO");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/whatbeg/p/4053710.html