Interesting Array 题解
题目大意
构造一个序列 l r q
的式子,其意义是:
题意分析
看上去是构造题,实际上是数据结构题。
我们不妨先令初始时
为了满足某一个限制条件
,在二进制表示中, 为 的位置均为 。 ,在二进制表示中, 为 的位置区间内至少有一个数该位为 。
我们发现,同时构造出满足两个条件的序列比较麻烦,且不好判断无解,因此,我们可以让一个条件成为构造的依据,另一个条件成为判断的依据。
具体的说,我们只需要构造出满足其中一个条件的序列,再逐一判断每个区间是否满足另一个条件即可。
因此,我们不妨先构造一个满足条件
那么,现在问题就变成了如果构造一个满足条件
这其实很简单,我们只需要用线段树进行区间按位或和区间求按位与就行了。
这是因为为了满足条件
综上,我们只需要维护一颗线段树,支持区间或和区间求与即可。
代码
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】