题解: 每个点x,设置其前驱为离其最近的w-x的位置 每次修改可能影响O(n)个位置: w-x x x x x x x… 这样后面每个位置的前驱都是w-x 如果修改了w-x的值,这样会导致O(n)个修改
注意到这个是存在性判定 如果存在两个
(
i
1
,
j
1
)
,
(
i
2
,
j
2
)
(i_1,j_1),(i_2,j_2)
(i1?,j1?),(i2?,j2?)使得
a
[
i
1
]
+
a
[
j
1
]
=
w
,
a
[
i
2
]
+
a
[
j
2
]
=
w
a[i_1]+a[j_1]=w,a[i_2]+a[j_2]=w
a[i1?]+a[j1?]=w,a[i2?]+a[j2?]=w,而且
[
i
2
,
j
2
]
[i_2,j_2]
[i2?,j2?]包含了
[
i
1
,
j
1
]
[i_1,j_1]
[i1?,j1?],则
(
i
2
,
j
2
)
(i_2,j_2)
(i2?,j2?)没有任何意义 这样每个点只存在
O
(
1
)
O(1)
O(1)个配对关系
由于是存在性,所以我们维护b[i]表示每个点的前驱 如果区间
[
l
,
r
]
[l,r]
[l,r]内
b
[
i
]
b[i]
b[i]最大值在
[
l
,
r
]
[l,r]
[l,r]中,则存在,否则不存在 这样只需要线段树求最大值,和multiset维护前驱后继即可
—来自李欣隆大师的讲解。
代码:
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn=5e5+10;
bool previsited[maxn],sufvisited[maxn];
multiset<int> ss[maxn];
int pre[maxn],suf[maxn];
int a[maxn];
int imax[maxn<<2];
void update(int node,int start,int ends,int pos,int val){
if(start==ends){
imax[node]=val;
return ;
}
int mid=(start+ends)>>1;
if(pos<=mid) update(node<<1,start,mid,pos,val);
else update(node<<1|1,mid+1,ends,pos,val);
imax[node]=max(imax[node<<1],imax[node<<1|1]);
}
int query(int node,int start,int ends,int l,int r){
if(l<=start&&ends<=r){
return imax[node];
}
int mid=(start+ends)>>1;
int res=0;
if(l<=mid) res=max(res,query(node<<1,start,mid,l,r));
if(mid<r) res=max(res,query(node<<1|1,mid+1,ends,l,r));
return res;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,w;
cin>>n>>m>>w;
for(int i=1;i<=n;i++){
cin>>a[i];
if(ss[w-a[i]].size()!=0){
set<int>::iterator it=ss[w-a[i]].end();
it--;
if(!sufvisited[*it]){
sufvisited[*it]=true;
previsited[i]=true;
pre[i]=*it;
suf[*it]=i;
update(1,1,n,i,pre[i]);
}
}
ss[a[i]].insert(i);
}
int cnt=0;
for(int i=1;i<=m;i++){
int opt;
cin>>opt;
if(opt==1){
int x,y;
cin>>x>>y;
if(a[x]==y) continue;
ss[a[x]].erase(x);
ss[y].insert(x);
sufvisited[x]=false;
previsited[x]=false;
if(pre[x]!=0) sufvisited[pre[x]]=false;
if(suf[x]!=0) previsited[suf[x]]=false;
update(1,1,n,x,0);
if(suf[x]) update(1,1,n,suf[x],0);
if(pre[x]!=0){
set<int>::iterator it=ss[w-a[pre[x]]].upper_bound(pre[x]);
suf[pre[x]]=0;
if(it!=ss[w-a[pre[x]]].end()&&!previsited[*it]){
previsited[*it]=true;
sufvisited[pre[x]]=true;
suf[pre[x]]=*it;
pre[*it]=pre[x];
update(1,1,n,*it,pre[*it]);
}
else{
}
}
if(suf[x]!=0){
set<int>::iterator it=ss[w-a[suf[x]]].lower_bound(suf[x]);
pre[suf[x]]=0;
if(it!=ss[w-a[suf[x]]].begin()){
it--;
if(*it<suf[x]&&!sufvisited[*it]){
sufvisited[*it]=true;
previsited[suf[x]]=true;
pre[suf[x]]=*it;
suf[*it]=suf[x];
update(1,1,n,suf[x],pre[suf[x]]);
}
}
}
a[x]=y;
pre[x]=suf[x]=0;
set<int>::iterator it=ss[w-a[x]].lower_bound(x);
if(it!=ss[w-a[x]].begin()){
it--;
if(*it<x){
if(!sufvisited[*it]){
sufvisited[*it]=true;
previsited[x]=true;
pre[x]=*it;
suf[*it]=x;
update(1,1,n,x,pre[x]);
}
else {
if(suf[*it]>x){
pre[suf[*it]]=0;
previsited[suf[*it]]=false;
pre[x]=*it;
suf[*it]=x;
previsited[x]=true;
update(1,1,n,x,*it);
}
}
}
}
it=ss[w-a[x]].upper_bound(x);
if(it!=ss[w-a[x]].end()){
if(!previsited[*it]){
previsited[*it]=true;
sufvisited[x]=true;
pre[*it]=x;
suf[x]=*it;
update(1,1,n,suf[x],pre[suf[x]]);
}
else{
if(pre[*it]<x){
suf[pre[*it]]=0;
sufvisited[pre[*it]]=false;
pre[*it]=x;
sufvisited[x]=true;
suf[x]=*it;
update(1,1,n,*it,x);
}
}
}
}
else{
int l,r;
cin>>l>>r;
l=l^cnt,r=r^cnt;
int ans=query(1,1,n,l,r);
if(ans>=l){
cnt++;
cout<<"Yes"<<endl;
}
else cout<<"No"<<endl;
}
}
}
|