• 2017-10-22模拟赛T2 或(or.*)


    题面


    【题目描述】
    你需要构造一个长度为 n 的数列 X,当中的数字范围从 0 到 2^30-1。除此之外你需要
    满足 m 个条件,第 i 个条件为 X[li]|X[li+1]|……|X[ri]=pi。|为按位或运算。
    【输入描述】
    第一行输入两个整数 n,m
    接下来的 m 行每行输入三个整数 li,ri,pi
    【输出描述】
    如果存在这样的序列,第一行输出 Yes,否则输出 No。
    如果存在这样的序列,第二行输出 n 个数,为数列 X。
    【样例】
    输入
    2 1
    1 2 1

    输出
    Yes
    1 1
    【数据范围】
    对于 30%的数据,n,m<=1000。
    对于另外 30%的数据,pi<=1。
    对于 100%的数据,n,m<=100000,1<=li<=ri<=n,0<=pi<2^30。

    题解


    又是一道位运算的题目(感觉是最简单的一道……)

    题意还是比较清楚的,这里不细说了。

    "对于另外30%的数据",出题人在这里是不是给了一个小小的提示?

    众所周知,位运算有一个性质,即对于每一个位是独立的,因此想到分开考虑每个位的情况。

    对于每个条件的pi的每一位,如果这一位为0,那么这个区间内所有的数的这一位显然都为0。

    因此想到如下做法:

    先把数列内所有数设为230-1。

    对于每个条件的pi的每一位,如果这一位为0,那么将该区间内所有数的这一位置0,最后判断每个条件是否成立即可。

    用线段树维护数列,只需记录区间内所有数的或即可。复杂度O(mlog2n)

    具体细节见代码。关于位运算的操作,这里不多说了。

    代码


     1 #include <stdio.h>
     2 #define N 100010
     3 #define reg register
     4 const int pv=(1<<30)-1;
     5 int n,m,l[N],r[N],a[N];
     6 struct node{int o,l;}t[270000];
     7 void build(int l,int r,int k) {
     8     t[k].o=pv;t[k].l=0;
     9     if(l!=r) {
    10         build(l,l+r>>1,k<<1);
    11         build((l+r>>1)+1,r,k<<1|1);
    12     }
    13 }
    14 void pushdown(int k) {
    15     reg int x=t[k].l;
    16     t[k<<1].o&=~x;
    17     t[k<<1].l|=x;
    18     t[k<<1|1].o&=~x;
    19     t[k<<1|1].l|=x;
    20     t[k].l=0;
    21 }
    22 void setzero(int l,int r,int a,int b,int c,int k) {
    23     if(l==a&&r==b) {
    24         t[k].o&=~c;t[k].l|=c;
    25         return;
    26     }
    27     pushdown(k);
    28     reg int mid=l+r>>1;
    29     if(b<=mid) setzero(l,mid,a,b,c,k<<1);
    30     else if(a>mid) setzero(mid+1,r,a,b,c,k<<1|1);
    31     else {
    32         setzero(l,mid,a,mid,c,k<<1);
    33         setzero(mid+1,r,mid+1,b,c,k<<1|1);
    34     }
    35 }
    36 int query(int l,int r,int a,int b,int k) {
    37     if(l==a&&r==b) return t[k].o;
    38     pushdown(k);
    39     reg int mid=l+r>>1;
    40     if(b<=mid) return query(l,mid,a,b,k<<1);
    41     else if(a>mid) return query(mid+1,r,a,b,k<<1|1);
    42     else {
    43         return query(l,mid,a,mid,k<<1)|query(mid+1,r,mid+1,b,k<<1|1);
    44     }
    45 }
    46 void output(int l,int r,int k) {
    47     if(l==r) {
    48         printf("%d ",t[k].o);
    49         return;
    50     }
    51     pushdown(k);
    52     output(l,l+r>>1,k<<1);
    53     output((l+r>>1)+1,r,k<<1|1);
    54 }
    55 int main() {
    56     scanf("%d%d",&n,&m);
    57     build(1,n,1);
    58     for(int i=0;i<m;++i) {
    59         scanf("%d%d%d",l+i,r+i,a+i);
    60         setzero(1,n,l[i],r[i],~a[i],1);
    61     }
    62     for(int i=0;i<m;++i) {
    63         if(query(1,n,l[i],r[i],1)!=a[i]) {
    64             puts("No");
    65             return 0;
    66         }
    67     }
    68     puts("Yes");
    69     output(1,n,1);
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    读 Zepto 源码之内部方法
    读Zepto源码之代码结构
    vue-auto-focus: 控制自动聚焦行为的 vue 指令
    vue-lazy-render: 延迟渲染大组件,增强页面切换流畅度
    用vue实现模态框组件
    谷歌插件Image downloader开发之popup
    关于const
    Python线程指南(转自AstralWind)
    PyQt中的图形绘制
    sizeof和strlen之间的区别
  • 原文地址:https://www.cnblogs.com/hotwords/p/7719152.html
Copyright © 2020-2023  润新知