Train of thought

For the interval [L,r][L,r][L,r], divide and conquer can be used to solve the answer to a single query. Specifically, there are three intervals to satisfy the question:

  • It’s completely in the left half
  • It’s completely on the right
  • Across left and right

You can use the ruler method to calculate the third answer (since bitwise or bitwise does not decrease the answer, so every time you move the left endpoint to the right, the right endpoint does not decrease), and then directly maintain the left and right interval answer. If the complexity is O(Nlog⁡N)O(N\log N)O(NlogN), consider how to optimize the complexity.

At this time, we have already maintained the sum of suffixes bitwise or on the left interval in advance, and the sum of prefixes bitwise or on the right interval. Considering these sums alone, it is found that at most there are only log⁡amax\log a_{Max}logamax distinct digits. Since bitwise or bitwise does not decrease the number of 111 in binary, any difference must be caused by some extra 111 bits, and the position of the same sum is continuous. Therefore, for each interval, the maintenance of its prefix, suffix, and the position of the change in the scale is only needed in the log⁡amax\log a_{Max}logamax position, directly optimize the original complexity of NNN. ⋅log⁡amax\log N\cdot \log a_{Max}logN⋅logamax.

Since there are still modifications to be made, use the line tree to maintain it.

code

#include<bits/stdc++.h>
#define lc p<<1
#define rc p<<1|1
#definerep(i,st,ed) for(int i=st; i<=ed; ++i)
#definebl(u,i) for(int i=head[u]; i; i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
#define mp make_pair
#define eb emplace_back
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read(a) {}
void OP(a) {}
void op(a) {}
template <typename T, typename. T2>inline void read(T &_, T2 &... oth)
{
    int__ =0; _ =0;
    char ch=getchar(a);while(!isdigit(ch))
    {
        if(ch==The '-') __ =1;
        ch=getchar(a); }while(isdigit(ch))
    {
        _=_*10+ch- 48;
        ch=getchar(a); } _ = __? - _ : _;read(oth...) ; }template <typename T>
void Out(T _)
{
    if(_ <0)
    {
        putchar(The '-'); _ = - _; }if(_ > =10)
       Out(_ /10);
    putchar(_ %10+'0');
}
template <typename T, typename. T2>inline void OP(T _, T2... oth)
{
	Out(_).putchar('\n');
	OP(oth...) ; }template <typename T, typename. T2>inline void op(T _, T2... oth)
{
	Out(_).putchar(' ');
	op(oth...) ; }/ * # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # * /
const ll N=1E5+10;
ll n,m,x;
ll a[N],ans[4*N];
vector<pii> pre[4*N],nxt[4*N];
ll calc(ll p,ll al,ll ar)
{
	ll R=0,ret=0;
	for(int L=nxt[lc].size(a)- 1; L>=0; --L) {if(al>nxt[lc][L].first)
			continue;
		ll lsum=nxt[lc][L].second;
		while(R<pre[rc].size() && pre[rc][R].first<=ar && (lsum | pre[rc][R].second)<x)
			++R;
		if(R==pre[rc].size() || pre[rc][R].first>ar)
			break;
		ll PRE;
		if(L==nxt[lc].size(a)- 1)
			PRE=al;
		else
			PRE=max(al,nxt[lc][L+1].first+1);
		ret+=(ar-pre[rc][R].first+1)*(nxt[lc][L].first-PRE+1);
	}
	return ret;
}
void update(ll p,ll l,ll r)
{
	pre[p]=pre[lc];
	ll sum=pre[p].back().second;
	for(auto it:pre[rc])
		if((sum | it.second)! =sum) pre[p].eb(it.first,sum |= it.second);
	
	nxt[p]=nxt[rc];
	sum=nxt[p].back().second;
	for(auto it:nxt[lc])
		if((sum | it.second)! =sum) nxt[p].eb(it.first,sum |= it.second);
	
	ans[p]=ans[lc]+ans[rc]+calc(p,l,r);
}
void build(ll p,ll l,ll r)
{
	if(l==r)
	{
		pre[p].eb(l,a[l]);
		nxt[p].eb(l,a[l]);
		if(a[l]>=x)
			ans[p]=1;
		return;
	}
	ll mid=(l+r)>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
	update(p,l,r);
}
void modify(ll p,ll l,ll r,ll pos,ll val)
{
	if(l==r)
	{
		pre[p].clear(a); nxt[p].clear(a); ans[p]=0;
		pre[p].eb(l,val);
		nxt[p].eb(l,val);
		if(val>=x)
			ans[p]=1;
		return;
	}
	ll mid=(l+r)>>1;
	if(pos<=mid)
		modify(lc,l,mid,pos,val);
	else
		modify(rc,mid+1,r,pos,val);
	update(p,l,r);
}
ll query(ll p,ll l,ll r,ll al,ll ar)
{
	if(al<=l && ar>=r)
		return ans[p];
	ll mid=(l+r)>>1;
	if(al>mid)
		return query(rc,mid+1,r,al,ar);
	if(ar<=mid)
		return query(lc,l,mid,al,ar);
	return query(lc,l,mid,al,ar)+query(rc,mid+1,r,al,ar)+calc(p,max(al,l),min(ar,r));
}
void print(a)
{
	for(auto it:nxt[2])
	{
		op(it.first,it.second);
		en;
	}
	en;
	for(auto it:pre[3])
	{
		op(it.first,it.second);
		en;
	}
	en;
}
int main(a)
{
	read(n,m,x);
	rep(i,1,n)
		read(a[i]);
	build(1.1,n);
	ll ty,l,r;
	while(m--)
	{
		read(ty,l,r);
		if(ty==1)
			modify(1.1,n,l,r);
		else
			OP(query(1.1,n,l,r)); }}Copy the code