题目链接
https://codeforces.com/contest/1004/problem/F
题解
这种水题都不会做了怎么。。
考虑一个序列的前缀 \(\text{or}\) 值只会变化 \(O(\log W)\) 次,于是线段树维护每个区间的前缀和后缀 \(\text{or}\) 值即可。
时间复杂度 \(O(n\log n\log W)\).
代码
#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define iter iterator
#define riter reversed_iterator
#define y1 Lorem_ipsum_dolor
#define pii pair<int,int>
using namespace std;
inline int read()
{
int x = 0,f = 1; char ch = getchar();
for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
return x*f;
}
const int mxN = 1e5;
const int lgA = 20;
int a[mxN+3];
int n,q,X;
struct Data
{
pii pre[lgA+3],suf[lgA+3]; llong sum; int pren,sufn;
} sgt[mxN*4+3];
Data operator +(Data ls,Data rs)
{
Data ret; ret.sum = ls.sum+rs.sum; ret.pren = ret.sufn = 0;
llong cur = 0ll;
for(int i=1,j=rs.pren+1; i<=ls.sufn; i++)
{
while(j>1&&(rs.pre[j-1].first|ls.suf[i].first)>=X) {j--; cur += rs.pre[j].second;}
ret.sum += 1ll*ls.suf[i].second*cur;
}
for(int i=1; i<ls.pren; i++) {ret.pre[++ret.pren] = ls.pre[i];}
pii tmp = ls.pre[ls.pren];
for(int i=1; i<=rs.pren; i++)
{
if((tmp.first|rs.pre[i].first)==tmp.first) {tmp.second += rs.pre[i].second;}
else
{
ret.pre[++ret.pren] = tmp;
tmp.first |= rs.pre[i].first; tmp.second = rs.pre[i].second;
}
}
ret.pre[++ret.pren] = tmp;
for(int i=1; i<rs.sufn; i++) {ret.suf[++ret.sufn] = rs.suf[i];}
tmp = rs.suf[rs.sufn];
for(int i=1; i<=ls.sufn; i++)
{
if((tmp.first|ls.suf[i].first)==tmp.first) {tmp.second += ls.suf[i].second;}
else
{
ret.suf[++ret.sufn] = tmp;
tmp.first |= ls.suf[i].first; tmp.second = ls.suf[i].second;
}
}
ret.suf[++ret.sufn] = tmp;
return ret;
}
void build(int u,int le,int ri)
{
if(le==ri) {sgt[u].pren = sgt[u].sufn = 1,sgt[u].pre[1] = sgt[u].suf[1] = mkpr(a[le],1),sgt[u].sum = a[le]>=X?1:0; return;}
int mid = (le+ri)>>1;
build(u<<1,le,mid); build(u<<1|1,mid+1,ri);
sgt[u] = sgt[u<<1]+sgt[u<<1|1];
}
void modify(int u,int le,int ri,int pos,int x)
{
if(le==ri) {sgt[u].pre[1] = sgt[u].suf[1] = mkpr(x,1),sgt[u].sum = x>=X?1:0; return;}
int mid = (le+ri)>>1;
if(pos<=mid) modify(u<<1,le,mid,pos,x); else modify(u<<1|1,mid+1,ri,pos,x);
sgt[u] = sgt[u<<1]+sgt[u<<1|1];
}
Data query(int u,int le,int ri,int lb,int rb)
{
if(le>=lb&&ri<=rb) {return sgt[u];}
int mid = (le+ri)>>1;
if(rb<=mid) {return query(u<<1,le,mid,lb,rb);}
else if(lb>mid) {return query(u<<1|1,mid+1,ri,lb,rb);}
else {return query(u<<1,le,mid,lb,mid)+query(u<<1|1,mid+1,ri,mid+1,rb);}
}
int main()
{
n = read(),q = read(),X = read();
for(int i=1; i<=n; i++) a[i] = read();
build(1,1,n);
while(q--)
{
int opt = read();
if(opt==1)
{
int u = read(),x = read();
modify(1,1,n,u,x);
}
else
{
int l = read(),r = read();
Data ans = query(1,1,n,l,r);
printf("%I64d\n",ans.sum);
}
}
return 0;
}