码迷,mamicode.com
首页 > 其他好文 > 详细

Sonya and Bitwise OR CodeForces - 1004F (线段树)

时间:2019-07-12 21:16:58      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:back   air   sony   问答   set   span   queue   math   utc   

大意: 给定序列$a$, 给定整数$x$. 两种操作(1)单点修改 (2)给定区间$[l,r]$,求有多少子区间满足位或和不少于$x$.

 

假设不带修改. 固定右端点, 合法区间关于左端点单调的. 可以预处理出最近的合法的左端点位置.那么每次询问答案就为$\sum\limits_{\substack{pre[i]\ge l\\ l \le i\le r}}(pre[i]-l+1)$. 用二维数点的方法处理即可.

 

带修改的话, 关键是要注意到或和最多改变$20$次, 线段树记录下来改变的位置, 暴力合并即可.

#include <iostream>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl ‘\n‘
#define DB(a) ({REP(__i,1,n) cout<<a[__i]<<‘ ‘;hr;})
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;

const int N = 1e5+10;
int n,m,X,a[N];
struct _ {
	int lnum,rnum,x,L,R;
	ll ans;
	pii l[22],r[22];
	_ () {}
	_ (int lnum,int rnum,int x,int L,int R,ll ans):lnum(lnum),rnum(rnum),x(x),L(L),R(R),ans(ans) {}
	_ (int pos, int val) {
		L=R=l[1].y=r[1].y=pos;
		l[1].x=r[1].x=x=val;
		ans=(val<X);
		lnum=rnum=1;
	}
	_ operator + (const _& rhs) const {
		_ ret(lnum,rhs.rnum,x|rhs.x,L,rhs.R,ans+rhs.ans);
		memcpy(ret.l,l,sizeof l);
		memcpy(ret.r,rhs.r,sizeof r);
		for (int i=rnum,j=0; i; --i) {
			while (j<rhs.lnum&&(r[i].x|rhs.l[j+1].x)<X) ++j;
			ret.ans += (ll)(r[i].y-(i<rnum?r[i+1].y:L-1))*((j<rhs.lnum?rhs.l[j+1].y:rhs.R+1)-rhs.L);
		}
		REP(i,1,rhs.lnum) if ((rhs.l[i].x|x)!=ret.l[ret.lnum].x) { 
			(ret.l[++ret.lnum]=rhs.l[i]).x |= x;
		}
		REP(i,1,rnum) if ((r[i].x|rhs.x)!=ret.r[ret.rnum].x) { 
			(ret.r[++ret.rnum]=r[i]).x |= rhs.x;
		}
		return ret;
	}
} tr[N<<2];
void build(int o, int l, int r) {
	if (l==r) tr[o]=_(l,a[l]);
	else build(ls),build(rs),tr[o]=tr[lc]+tr[rc];
}
void update(int o, int l, int r, int x, int v) {
	if (l==r) tr[o]=_(x,v);
	else {
		mid>=x?update(ls,x,v):update(rs,x,v);
		tr[o]=tr[lc]+tr[rc];
	}
}
_ query(int o, int l, int r, int ql, int qr) {
	if (ql<=l&&r<=qr) return tr[o];
	if (mid>=qr) return query(ls,ql,qr);
	if (mid<ql) return query(rs,ql,qr);
	return query(ls,ql,qr)+query(rs,ql,qr);
}
int main() {
	scanf("%d%d%d", &n, &m, &X);
	REP(i,1,n) scanf("%d", a+i);
	build(1,1,n);
	while (m--) {
		int op,x,y;
		scanf("%d%d%d", &op, &x, &y);
		if (op==1) update(1,1,n,x,y);
		else printf("%lld\n",(y-x+1ll)*(y-x+2)/2-query(1,1,n,x,y).ans);
	}
}

 

Sonya and Bitwise OR CodeForces - 1004F (线段树)

标签:back   air   sony   问答   set   span   queue   math   utc   

原文地址:https://www.cnblogs.com/uid001/p/11178047.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!