ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【题解】【CF1004F Sonya and Bitwise OR】

2022-05-05 19:04:11  阅读:175  来源: 互联网

标签:suf ch int 题解 sum pos Bitwise Sonya 按位


Analysis

显然用线段树来维护。考虑快速求出左右端点分居左右区间的方案数。
首先按位或和是满足单调性的,按位或的数越多,和越大,那么从左到右枚举右端点,左端点的可行范围一定是从左区间的左端点到左区间的某个位置,且这个位置是递增的。
那么我们就有了单次pushup复杂度为O(区间长度)的做法。
但实际上二进制上某一位一旦变成1,之后再或上任何数都不会变,因此一个区间最多有log(值域)个不同的前/后缀按位或和。对于线段树每个区间,用vector维护前/后缀按位或和变化的位置和按位或和。这样单次pushup就是log(值域)了。可以通过本题。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int> 
inline int read()
{
	int x=0,w=1;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if(ch=='-') {w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*w;
}
inline void write(int x)
{
	if(x<0) putchar('-'),x=~(x-1);
	if(x>9) write(x/10);
	putchar('0'+x%10);
}
const int N=1e5+100;
int n,m,k,a[N];
struct node{
	int l,r,sum;
	vector<pii>pre,suf;
}t[N<<2];
void pushup(int x)
{
	t[x].sum=t[x<<1].sum+t[x<<1|1].sum;
	t[x].pre.clear();t[x].suf.clear();
	for(int i=0;i<t[x<<1].pre.size();++i)
	{
		t[x].pre.push_back(t[x<<1].pre[i]);
	} 
	int sum=t[x].pre.back().second;
	for(int i=0;i<t[x<<1|1].pre.size();++i){
		if((sum|t[x<<1|1].pre[i].second)!=sum){
			sum|=t[x<<1|1].pre[i].second;
			t[x].pre.push_back({t[x<<1|1].pre[i].first,sum});
		}
	}
	for(int i=t[x<<1|1].suf.size()-1;i>=0;--i) t[x].suf.push_back(t[x<<1|1].suf[i]);
	sum=t[x].suf.back().second;
	for(int i=t[x<<1].suf.size()-1;i>=0;--i){
		if((sum|t[x<<1].suf[i].second)!=sum){
			sum|=t[x<<1].suf[i].second;
			t[x].suf.push_back({t[x<<1].suf[i].first,sum});
		}
	}
	reverse(t[x].suf.begin(),t[x].suf.end());
	sum=0;
	int mid=t[x].l+t[x].r>>1,pos=0;
	for(int i=0;i<t[x<<1|1].pre.size();++i)
	{
		while(pos+1<t[x<<1].suf.size()&&(t[x<<1].suf[pos+1].second|t[x<<1|1].pre[i].second)>=k) pos++;
		if((t[x<<1].pre.back().second|t[x<<1|1].pre[i].second)>=k)sum+=(t[x<<1].suf[pos].first-t[x].l+1)*((i==t[x<<1|1].pre.size()-1?t[x].r+1:t[x<<1|1].pre[i+1].first)-t[x<<1|1].pre[i].first);
		mid=t[x<<1|1].pre[i].first;
	}
	t[x].sum+=sum;
}
void build(int x,int l,int r)
{
	t[x].l=l,t[x].r=r;
	if(l==r){
		if(a[l]>=k) t[x].sum=1;
		t[x].pre.push_back({l,a[l]});t[x].suf.push_back({r,a[r]});return;
	}
	int mid=l+r>>1;
	build(x<<1,l,mid);build(x<<1|1,mid+1,r);
	pushup(x);
}
int query(int x,int l,int r)
{
	if(t[x].l>=l&&t[x].r<=r) return t[x].sum;
	int mid=t[x].l+t[x].r>>1,res;
	if(l>mid) return query(x<<1|1,l,r);
	if(r<=mid) return query(x<<1,l,r);
	res=query(x<<1,l,r)+query(x<<1|1,l,r);
	l=max(l,t[x].l),r=min(r,t[x].r);int pos=0;for(int i=0;i<t[x<<1].suf.size();++i) if(t[x<<1].suf[i].first<l) pos++;
	for(int i=0;i<t[x<<1|1].pre.size();++i){
		if(t[x<<1|1].pre[i].first>r) break;
		while(pos+1<t[x<<1].suf.size()&&(t[x<<1].suf[pos+1].second|t[x<<1|1].pre[i].second)>=k) pos++;
		if((t[x<<1].suf[pos].second|t[x<<1|1].pre[i].second)>=k) res+=(t[x<<1].suf[pos].first-l+1)*(min(r+1,(i==t[x<<1|1].pre.size()-1?t[x].r+1:t[x<<1|1].pre[i+1].first))-t[x<<1|1].pre[i].first);
		mid=t[x<<1|1].pre[i].first;
	}
	return res;
}
void change(int x,int pos,int val)
{
	if(t[x].l==t[x].r){
		if(val>=k) t[x].sum=1;else t[x].sum=0;
		t[x].pre[0].second=t[x].suf[0].second=val;return;
	}
	int mid=t[x].l+t[x].r>>1;
	if(pos<=mid) change(x<<1,pos,val);
	else change(x<<1|1,pos,val);
	pushup(x);
}
signed main()
{
    n=read();m=read();k=read();
    for(int i=1;i<=n;++i) a[i]=read();
    build(1,1,n);
    for(int i=1;i<=m;++i)
    {
    	int op=read(),x=read(),y=read();
    	if(op-1){
    		write(query(1,x,y));puts("");
		}
		else change(1,x,y);
	}
	return 0;
}

标签:suf,ch,int,题解,sum,pos,Bitwise,Sonya,按位
来源: https://www.cnblogs.com/glq-Blog/p/16225767.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有