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;
}

时间: 2024-07-30 23:10:15

Codeforces Round #275 Div.1 B Interesting Array --线段树的相关文章

Codeforces Round #426 (Div. 2) D. The Bakery(线段树维护dp)

题目链接: Codeforces Round #426 (Div. 2) D. The Bakery 题意: 给你n个数,划分为k段,每段的价值为这一段不同的数的个数,问如何划分,使得价值最大. 题解: 考虑dp[i][j]表示划分为前j个数划分为i段的最大价值,那么这就是一个n*n*k的dp, 考虑转移方程dp[i][j]=max{dp[i][k]+val[k+1][j]},我们用线段树去维护这个max,线段树上每个节点维护的值是dp[i][k]+val[k+1][j],对于每加进来的一个数a

Codeforces Round #424 (Div. 2) E. Cards Sorting(线段树)

题目链接:Codeforces Round #424 (Div. 2) E. Cards Sorting 题意: 将n个数放进一个队列,每次检查队首,看看是不是队列中最小的数,如果是就扔掉,如果不是就放到队尾. 这样直到队列为空,为需要操作多少次. 题解: 考虑用两个指针模拟,最开始now指针指向第一个数,然后nxt指针指向下一个将要被删除的数. 然后我们要算出这里需要移动多少步,然后删掉这个数,一直重复操作,直到将全部的数删完. nxt指针可以用set来维护,now指针可以用并查集来维护. 计

Codeforces Round #603 (Div. 2) E. Editor(线段树)

链接: https://codeforces.com/contest/1263/problem/E 题意: The development of a text editor is a hard problem. You need to implement an extra module for brackets coloring in text. Your editor consists of a line with infinite length and cursor, which point

Codeforces Round #271 (Div. 2) F.Ant colony(线段树 + 统计区间内某数的个数)

F. Ant colony Mole is hungry again. He found one ant colony, consisting of n ants, ordered in a row. Each ant i (1 ≤ i ≤ n) has a strength si. In order to make his dinner more interesting, Mole organizes a version of «Hunger Games» for the ants. He c

Codeforces Round #244 (Div. 2) B. Prison Transfer 线段树rmq

B. Prison Transfer Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem/427/B Description The prison of your city has n prisoners. As the prison can't accommodate all of them, the city mayor has decided to transfer c

Codeforces Round #222 (Div. 1) D. Developing Game 线段树有效区间合并

D. Developing Game Pavel is going to make a game of his dream. However, he knows that he can't make it on his own so he founded a development company and hired n workers of staff. Now he wants to pick n workers from the staff who will be directly res

Codeforces Round #530 (Div. 2) E (树形dp+线段树)

链接: 题意: 给你一棵树,树上有n个节点,每个节点上有ai块饼干,在这个节点上的每块饼干需要花费bi时间,有两个玩家,玩家一可以移动到当前点的子节点也可以申请游戏结束返回根节点并吃沿途的饼干,玩家二可以删除当前点到儿子节点的一条边,走路和吃饼干都消耗时间,会给出一个总时间,在总时间内尽可能的多吃饼干,问最多能吃多少个? 思路: 由于是玩家一先手,那么最开始的最大边则不会被删除,但之后路途的最大边都会被玩家二删除,所以我们对于当前点我们需要求: 1.如果现在回头那么最多可以吃到多少饼干 2.向下

Codeforces Round #587 (Div. 3) F Wi-Fi(线段树+dp)

题意:给定一个字符串s 现在让你用最小的花费 覆盖所有区间 思路:dp[i]表示前i个全覆盖以后的花费 如果是0 我们只能直接加上当前位置的权值 否则 我们可以区间询问一下最小值 然后更新 #include <bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const double eps = 1e-6; const int N = 2e5+7; typedef long long ll; const ll mod

Codeforces Round #275 (Div. 1)A. Diverse Permutation 构造

Codeforces Round #275 (Div. 1)A. Diverse Permutation Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/482/problem/A Description Permutation p is an ordered set of integers p1,   p2,   ...,   pn, consisting of n distinct posi