敲了很久所以mark一下,辣鸡!
原题见CF 482B
试给出n个数,满足m个条件,每个条件即第l个数到第r个数这连续几个数的&
值等于q。n和m范围为
1到105
,q的范围为0到
230
.
分析
同一个数如果要满足多个条件,则这个数值为q的或
。
每次满足的条件要对一个区间的值取或
(旧值或
新值),对于区间操作,利用线段树来操作。
所有条件标记完以后,向下更新到所有结点。
再反过来检验是否满足m个条件(之前的或
操作可能会使一些位没有0),即线段树的查询操作。ATTENTION:先要从叶节点向上更新区间的&和之前没更新竟然过了,数据太弱了。
写完之后感觉也不是很难嘛……辣鸡
附代码
/*--------------------------------------------
* File Name: CF 482B
* Author: Danliwoo
* Mail: Danliwoo@outlook.com
* Created Time: 2016-07-08 10:15:09
--------------------------------------------*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 101000
#define M 32
int n, m, tre[N*3];
struct node
{
int l, r, v;
void pr(){
printf("%d %d %d %d\n", m, l, r, v);
}
}p[N];
void update(int rt, int l, int r, int bg, int ed, int v){
if(r < bg || ed < l || bg > ed) return;
if(bg <= l && r <= ed){
tre[rt] |= v;
return;
}
int mid = l+r >> 1;
update(rt<<1, l, mid, bg, ed, v);
update(rt<<1|1, mid+1, r, bg, ed, v);
}
void down(int rt, int l, int r){
if(l == r) return;
tre[rt<<1] |= tre[rt];
tre[rt<<1|1] |= tre[rt];
int mid = l+r >> 1;
down(rt<<1, l, mid);
down(rt<<1|1, mid+1, r);
}
int test(int rt, int l, int r, int bg, int ed){
if(r < bg || ed < l || bg > ed) return 0x7fffffff;
if(bg <= l && r <= ed){
return tre[rt];
}
int res = 0x7fffffff, mid = l+r >> 1;
res &= test(rt<<1, l, mid, bg, ed);
res &= test(rt<<1|1, mid+1, r, bg, ed);
return res;
}
void pr(int rt, int l, int r){
if(l == r){
if(l > 1) printf(" ");
printf("%d", tre[rt]);
return;
}
int mid = r+l >> 1;
pr(rt<<1, l, mid);
pr(rt<<1|1, mid+1, r);
}
int change(int rt, int l, int r){
if(l == r) return tre[rt];
int mid = l+r >> 1;
change(rt<<1, l, mid);
change(rt<<1|1, mid+1, r);
return tre[rt] = tre[rt<<1] & tre[rt<<1|1];
}
bool solve(){
down(1, 1, n);
change(1, 1, n);
for(int i = 0;i < m;i++)
if(test(1, 1, n, p[i].l, p[i].r) != p[i].v)
return false;
printf("YES\n");
pr(1, 1, n);
printf("\n");
return true;
}
int main()
{
while(~scanf("%d%d", &n, &m)){
memset(tre, 0, sizeof(tre));
for(int i = 0;i < m;i++)
scanf("%d%d%d", &p[i].l, &p[i].r, &p[i].v);
memset(tre, 0, sizeof(tre));
for(int i = 0;i < m;i++)
update(1, 1, n, p[i].l, p[i].r, p[i].v);
if(!solve()) printf("NO\n");
}
return 0;
}