首页 > 其他分享 >Interesting Array 题解

Interesting Array 题解

时间:2023-06-05 17:00:30浏览次数:50  
标签:Interesting 题解 构造 序列 按位 条件 区间 Array

Interesting Array

题目大意

构造一个序列 \(a\),使其满足若干限制条件,每个限制条件是形如 l r q 的式子,其意义是:\(\&_{i=l}^ra_i=q\)。

题意分析

看上去是构造题,实际上是数据结构题。

我们不妨先令初始时 \(a\) 为一个全 \(0\) 序列,再逐一看每个限制条件。

为了满足某一个限制条件 \(l,r,p\),\([l,r]\) 区间的数必须符合以下两点:

  • \(1\),在二进制表示中,\(p\) 为 \(1\) 的位置均为 \(1\)。
  • \(2\),在二进制表示中,\(p\) 为 \(0\) 的位置区间内至少有一个数该位为 \(0\)。

我们发现,同时构造出满足两个条件的序列比较麻烦,且不好判断无解,因此,我们可以让一个条件成为构造的依据,另一个条件成为判断的依据。

具体的说,我们只需要构造出满足其中一个条件的序列,再逐一判断每个区间是否满足另一个条件即可。

因此,我们不妨先构造一个满足条件 \(1\) 的序列,再逐一对条件 \(2\) 进行判断。

那么,现在问题就变成了如果构造一个满足条件 \(1\) 的序列和如何对条件 \(2\) 进行判断。

这其实很简单,我们只需要用线段树进行区间按位或和区间求按位与就行了。

这是因为为了满足条件 \(1\),我们需要让区间的二进制表示包含 \(p\),这等价于于区间按位或 \(p\),而条件 \(2\) 与区间的按位与是 \(p\) 二者也等价。

综上,我们只需要维护一颗线段树,支持区间或和区间求与即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=100100;

int n,m,inp[N][3];

struct STn{int l,r,t,sum;};//sum表示区间与的结果,t是懒标记
struct ST{
    STn a[N<<2];
    void or_t(int p,int k){
        a[p].t|=k;a[p].sum|=k;//都或上k
    }
    void push_down(int p){//下放懒标记
        if(a[p].t){
            or_t(p<<1,a[p].t);
            or_t(p<<1|1,a[p].t);
            a[p].t=0;
        }
    }
    void build(int p,int l,int r){//简单建树
        a[p].l=l;a[p].r=r;a[p].t=0;
        if(a[p].l==a[p].r) return ;
        int mid=(a[p].l+a[p].r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
    }
    void or_all(int p,int l,int r,int k){//区间或
        if(l<=a[p].l&&a[p].r<=r){or_t(p,k);return ;}
        push_down(p);int mid=(a[p].l+a[p].r)>>1;
        if(l<=mid) or_all(p<<1,l,r,k);
        if(r>mid) or_all(p<<1|1,l,r,k);
        a[p].sum=a[p<<1].sum&a[p<<1|1].sum;
    }
    int and_all(int p,int l,int r){//区间求与
        if(l<=a[p].l&&a[p].r<=r) return a[p].sum;
        push_down(p);int mid=(a[p].l+a[p].r)>>1;
        if(r<=mid) return and_all(p<<1,l,r);
        if(l>mid) return and_all(p<<1|1,l,r);
        return and_all(p<<1,l,r)&and_all(p<<1|1,l,r);
    }
    void print(int p){//输出序列
        if(a[p].l==a[p].r){cout<<a[p].sum<<' ';return ;}
        push_down(p);int mid=(a[p].l+a[p].r)>>1;
        print(p<<1);print(p<<1|1);
    }
}tree;

int main(){
    scanf("%d%d",&n,&m);
    tree.build(1,1,n);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&inp[i][0],&inp[i][1],&inp[i][2]);
        tree.or_all(1,inp[i][0],inp[i][1],inp[i][2]);
    }
    for(int i=1;i<=m;i++)
        if(tree.and_all(1,inp[i][0],inp[i][1])!=inp[i][2]){cout<<"NO\n";return 0;} 
    cout<<"YES\n";
    tree.print(1);
    return 0;
}

标签:Interesting,题解,构造,序列,按位,条件,区间,Array
From: https://www.cnblogs.com/TKXZ133/p/17458275.html

相关文章

  • Sum of MSLCM 题解
    SumofMSLCM题目大意定义\(\text{MSLCM}(n)\)为所有满足该数集的\(\text{lcm}\)为\(n\)的数集中元素个数最多的数集的所有数字的和,现有多次询问,求\[\sum_{i=2}^n\text{MSLCM}(i)\]思路分析大水题。虽然看着这个东西很可怕,但仔细一想你就会发现,其实\(\text{MSLCM}(n)......
  • Java模拟表单提交编码不同导致乱码问题解决
    最近有个业务需要模拟表单提交到asp页面中,但是我的项目编码是UTF8,而asp页面是GB2312,中文字段提交后,到达数据库后是乱码.问题的解决在于模拟提交的时候指定编码:我用的HTTP框架是Unirest,代码如下:......
  • 安装Navicat遇到的问题解决
    1、如果遇到安装出现问题,并且不能激活,需要重新卸载安装。需要彻底卸载2、除了点击卸载安装之后,需要注册表删除掉所有的信息,以及删除掉在C:\ProgramFiles\PremiumSoft的Navicat删除掉3、删除注册表Win+R之后输入:regedit进入注册表3.1找到计算机\HKEY_CURRENT_USER\Softwar......
  • [ABC208E] Digit Products 题解
    DigitProducts题目大意求有多少个不大于\(n\)的正整数,使得该正整数各位乘积不大于\(k\)。思路分析观察数据范围,首先考虑数位DP。考虑设计记忆化搜索函数dfs(intpos,boollimit,boollead0,intmul)表示当前枚举到第\(\text{pos}\)位,第\(\text{pos}\)位是否受到限......
  • [ABC207E] Mod i 题解
    Modi题目大意给定一个序列\(a\),问将其划分成若干段,满足第\(i\)段的和是\(i\)的倍数的划分方案的个数。思路分析考虑DP,设\(f_{i,j}\)表示将序列中前\(i\)个数划分成\(j\)段,且满足条件的划分方案的个数,容易得出状态转移方程:\[f_{i,j}=\sumf_{k,j-1}(\sum_{h=k+1}......
  • [ABC205E] White and Black Balls 题解
    WhiteandBlackBalls题目大意将\(n\)个白球,\(m\)个黑球排成一列,要求满足\(\foralli\in[1,n+m],w_i\leb_i+k\),问存在多少种排法。其中\(w_i\)表示第\(i\)个球前的白球数量,\(b_i\)表示第\(i\)个球前的黑球数量。思路分析我们可以将一种排法映射成一条从\((0,0)......
  • [ABC205F] Grid and Tokens 题解
    GridandTokens题目大意给定\(n\)个点和一个\(H\timesW\)的网格,每个点可以放置在\((A_i,B_i)\)到\((C_i,D_i)\)的矩形中或不放,每一行或一列只能放置一个点,求最多能放多少个点。思路分析首先看数据范围,再结合题目给的限制条件,容易发现这是一道网络流。考虑建图,因为......
  • [ABC201E] Xor Distances 题解
    XorDistances题目大意给定一颗带边权无根树,定义\(\text{dis}(i,j)\)表示\(i,j\)两点在树上的最短路径的边权的异或和。求:\[\sum_{i=1}^n\sum_{j=i+1}^n\text{dis}(i,j)\]思路分析首先,容易证明:\[\text{dis}(i,j)=\text{dis}(i,x)\oplus\text{dis}(x,j)\]这个式子告诉我......
  • [ABC202E] Count Descendants 题解
    CountDescendants题目大意给定一颗以\(1\)为根的树,多次询问求某点的子树中深度为给定值的点的个数。思路分析对于每个深度开一个vector,从大到小存下这个深度的所有点的dfs序开始值和结束值,询问时只需要在对应深度的vector中二分作差即可。代码#include<iostream>#......
  • [ABC204E] Rush Hour 2 题解
    RushHour2题目大意给定一张无向图,边带两个参数\(c_i,d_i\),在\(t\)时间时经过第\(i\)条边所需的时间是\(c_i+\lfloor\frac{d_i}{t+1}\rfloor\),求在时间\(0\)时出发,在每个点可以停留非负整数时间,从点\(1\)到点\(n\)所需的最短时间。思路分析首先,容易发现在时间\(......