序列
这道题深刻地论证了分治算法的妙处,也形象地说明了序列题最好用分治算法
——————————————————————————————————————————————
本题正解的思路有点难想,强行构造出的分治合并方法非常巧妙(ZZ的解法)
——————————————————————————————————————————————
分
治
出
[
l
,
r
]
,
取
m
i
d
,
想
办
法
在
O
(
n
)
的
时
间
里
合
并
分治出[l,r],取mid,想办法在O(n)的时间里合并
分治出[l,r],取mid,想办法在O(n)的时间里合并
分
类
讨
论
:
分类讨论:
分类讨论:
- 若最小值在左边,即需要保证右边取的数都小于此值
- 若最小值在右边,即需保证左边取的数都小于此值
- 为了方便,我们把左右都存在最小值的归为以上某类讨论
但是由于序列并不单调,所以分类讨论之后不好直接做
——————————————————————————————————————————————
构造
由于是找最小值,所以我们用最小值来算比较方便
构
造
s
u
f
数
组
和
p
r
e
数
组
,
使
m
i
d
左
边
s
u
f
非
严
格
单
调
递
增
,
右
边
p
r
e
非
严
格
单
调
递
减
构造suf数组和pre数组,使mid左边suf非严格单调递增,右边pre非严格单调递减
构造suf数组和pre数组,使mid左边suf非严格单调递增,右边pre非严格单调递减
这样,就可以二分找出想要的值,
将
[
l
,
m
i
d
]
枚
举
两
次
,
一
次
从
大
到
小
,
一
次
从
小
到
大
,
这
样
就
能
很
快
更
新
出
最
值
(
当
然
也
可
以
左
右
各
枚
举
一
次
,
但
这
样
要
写
两
个
二
分
)
将[l,mid]枚举两次,一次从大到小,一次从小到大,这样就能很快更新出最值(当然也可以左右各枚举一次,但这样要写两个二分)
将[l,mid]枚举两次,一次从大到小,一次从小到大,这样就能很快更新出最值(当然也可以左右各枚举一次,但这样要写两个二分)
——————————————————————————————————————————————
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
int n;
int a[N],D;
int suf[N],pre[N],pos,tmp,x[N],s[1<<21];//不能开N*10,因为异或运算可能超过原数
int find(int l,int r,int val){
while(l<r){
int mid=(l+r)>>1;
if(pre[mid]>=val) l=mid+1;
else r=mid;
}
return l;
}
ll dfs(int l,int r){
ll ans=0;
if(l==r) {return (a[l]==D);}
int mid=(l+r)>>1;
suf[mid]=a[mid],pre[mid+1]=a[mid+1],x[mid+1]=0;
for(int i=mid+2;i<=r;i++) pre[i]=min(pre[i-1],a[i]),x[i]=(pre[i]^a[i]);
for(int i=mid-1;i>=l;i--) suf[i]=min(suf[i+1],a[i]);
pos=mid+1;
for(int i=mid;i>=l;i--){
int tmp=find(mid+1,r,suf[i]);
if(pre[r]>=suf[i]) tmp=r+1;
for(int j=pos;j<tmp;j++) s[a[j]]++;
ans+=s[(D^a[i]^suf[i])],pos=tmp;
}
for(int i=mid+1;i<=r;i++){s[a[i]]=0;}pos=r;
for(int i=l;i<=mid;i++){
int tmp=find(mid+1,r,suf[i]);
if(pre[r]>=suf[i]) tmp=r+1;
for(int j=pos;j>=tmp;j--) s[x[j]]++;//
ans+=s[(D^a[i])],pos=tmp-1;
}
for(int i=mid+1;i<=r;i++){s[x[i]]=0;}
return ans+dfs(l,mid)+dfs(mid+1,r);
}
int main(){
scanf("%d%d",&n,&D);
for(int i=1;i<=n;i++){scanf("%d",&a[i]);}
ll ansout=dfs(1,n);
printf("%lld",ansout);
}
——————————————————————————————————————————————