• 【SDOJ2820】or(或)


    题面

    构造一个长度为n的非负整数序列x,满足m个条件,第i个条件为x[li]|x[li+1]|…|x[ri]=pi。

    输入

    第一行两个整数n,m。接下来m行每行三个整数li,ri,pi。 

    输出

    如果存在这样的序列x,第一行输出Yes,第二行输出n个不超过2^30-1的非负整数表示x[1]~x[n],否则输出一行No。

    对于30%的数据,n,m<=1000。 

    对于另外30%的数据,pi<=1。

    对于100%的数据,n,m<=100000,1<=li<=ri<=n,0<=pi<2^30。

    分析

    几个显然的结论

    1.有0的位置必须所有数那一位全部为0

    2.有1的位置必须有一个数那一位为1

    所以其实可以拿p来构造,把所有数都设为230-1(二进制所有位都是1)

    拿p来&一下,原来是1的位置遇到0就会被弄成0,遇到1不会变,按照题目的意思去尝试修改(区间修改,线段树)

    最后需要检验一下,就区间取或

    这有一个结论

    (a&p)|(b&p)……(z&p)=(a|b|……|z)&p

    这就是为啥线段树可以合法合并

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100100
    #define ll long long 
    #define MAXN (1<<30)-1
    #define lc (p<<1)
    #define rc (p<<1|1)
    #define mid (t[p].l+t[p].r>>1)
    ll n,m;
    ll p[N],pl[N],pr[N];
    struct email
    {
        ll l,r,sum;
    }t[N*4];
    
    inline void pushup(ll p)
    {
        t[p].sum=t[lc].sum|t[rc].sum;
    } 
    
    inline void pushdown(ll p)
    {
        ll px=t[p].sum;
        t[lc].sum&=px;t[rc].sum&=px;
    }
    
    inline void build(ll p,ll l,ll r)
    {
        t[p].l=l;t[p].r=r;
        if(l==r)
        {
            t[p].sum=MAXN;
            return ;
        }
        ll bm=l+r>>1;
        build(lc,l,bm);build(rc,bm+1,r);
        pushup(p);
    }
    
    inline void update(ll p,ll ql,ll qr,ll x)
    {
        if(ql<=t[p].l&&qr>=t[p].r)
        {
            t[p].sum&=x;
            return ;
        }
        pushdown(p);
        if(ql<=mid)update(lc,ql,qr,x);
        if(qr>mid)update(rc,ql,qr,x);
        pushup(p);
    }
    
    inline ll query(ll p,ll ql,ll qr)
    {
        ll ret=0;
        if(ql<=t[p].l&&qr>=t[p].r)
            return t[p].sum;
        pushdown(p);
        if(ql<=mid)ret|=query(lc,ql,qr);
        if(qr>mid)ret|=query(rc,ql,qr);
        return ret;
    }
    
    int main()
    {
        scanf("%lld%lld",&n,&m);
        build(1,1,n);
        for(ll i=1;i<=m;i++)
        {
            scanf("%lld%lld%lld",&pl[i],&pr[i],&p[i]);
            update(1,pl[i],pr[i],p[i]);
        }
        for(ll i=1;i<=m;i++)
        {
            ll ret=query(1,pl[i],pr[i]);
            if(ret!=p[i])
            {printf("No
    ");return 0;}
        }
        printf("Yes
    ");
        for(ll i=1;i<=n;i++)
            printf("%lld ",query(1,i,i));
        return 0;
    }
    “Make my parents proud,and impress the girl I like.”
  • 相关阅读:
    SpringMVC中的@Controller和@RequestMapping到底什么鬼?
    String、StringBuffer和StringBulder
    对spring的理解是什么?
    Maven依赖解析
    【Java框架型项目从入门到装逼】第一节 Spring框架 IOC的丧心病狂解说
    python学习记录(二)安装python编辑器
    python学习记录(一)安装python
    C#.net ListView item 拖动排序实现方法
    使用sql语句实现跨数据库获取信息
    Asp.net弹出层并且有遮罩层
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9692002.html
Copyright © 2020-2023  润新知