解题思路
可将
A[i]
A
[
i
]
抽象为二维平面上的点
(i,A[i])
(
i
,
A
[
i
]
)
,询问就是求与给定点曼哈顿距离小于等于
k
k
的点数,修改则是加点操作。
把曼哈顿距离转化为切比雪夫距离,询问就变成了给定,转为切比雪夫距离后为
(x+y,x−y)
(
x
+
y
,
x
−
y
)
,求矩形
(x+y−k,x+y+k,x−y−k,x−y+k)
(
x
+
y
−
k
,
x
+
y
+
k
,
x
−
y
−
k
,
x
−
y
+
k
)
内部有多少点。
于是可以使用
CDQ
C
D
Q
分治,也可以大力
KD−tree
K
D
−
t
r
e
e
。
KD−tree
K
D
−
t
r
e
e
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
#include<set>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstdlib>
#define ll long long
using namespace std;
const int inf=100005;
const double alpha=0.75;
int tmp[100005],a[100005];
int n,m,cmpd,rot,tot;
struct tree{
int d[2],mx[2],mn[2];
int siz,ls,rs;
void clr(){
siz=1;ls=rs=0;
mx[0]=mn[0]=d[0];
mx[1]=mn[1]=d[1];
}
}s[100005];
bool operator < (const tree r1,const tree r2){
return r1.d[cmpd]==r2.d[cmpd] ? r1.d[cmpd^1]<r2.d[cmpd^1] : r1.d[cmpd]<r2.d[cmpd];
}
bool cmp(int r1,int r2){return s[r1]<s[r2];}
void pushup(int x,int k){
s[x].siz+=s[k].siz;
s[x].mx[0]=max(s[x].mx[0],s[k].mx[0]);
s[x].mx[1]=max(s[x].mx[1],s[k].mx[1]);
s[x].mn[0]=min(s[x].mn[0],s[k].mn[0]);
s[x].mn[1]=min(s[x].mn[1],s[k].mn[1]);
}
int build(int l,int r,int D){
int mid=l+r>>1;cmpd=D;
nth_element(tmp+l,tmp+mid,tmp+r+1,cmp);
int re=tmp[mid];
if(l<mid) pushup(re,s[re].ls=build(l,mid-1,D^1));
if(mid<r) pushup(re,s[re].rs=build(mid+1,r,D^1));
return re;
}
void dfs(int x){
if(!x) return ;
dfs(s[x].ls);dfs(s[x].rs);
tmp[++tot]=x;s[x].clr();
}
void rebuild(int &p,int D){
tot=0;dfs(p);
p=build(1,tot,D);
}
void Insert(int &p,int k,int D,bool flag){
if(!p) {p=k;return ;}
pushup(p,k);cmpd=D;
if(s[k]<s[p]){
if(!flag && s[s[p].ls].siz+1>alpha*s[p].siz) {Insert(s[p].ls,k,D^1,1);rebuild(p,D);}
else Insert(s[p].ls,k,D^1,flag);
}
else {
if(!flag && s[s[p].rs].siz+1>alpha*s[p].siz) {Insert(s[p].rs,k,D^1,1);rebuild(p,D);}
else Insert(s[p].rs,k,D^1,flag);
}
}
int query(int p,int x,int dx,int y,int dy){
if(!p || x>s[p].mx[0] || dx<s[p].mn[0] || y>s[p].mx[1] || dy<s[p].mn[1]) return 0;
if(x<=s[p].mn[0]&&dx>=s[p].mx[0]&&y<=s[p].mn[1]&&dy>=s[p].mx[1]) return s[p].siz;
int re=0;
if(s[p].d[0]>=x&&s[p].d[0]<=dx&&s[p].d[1]>=y&&s[p].d[1]<=dy) re++;
re+=query(s[p].ls,x,dx,y,dy)+query(s[p].rs,x,dx,y,dy);
return re;
}
int main(){
int x,k;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
s[i].d[0]=i+a[i];
s[i].d[1]=i-a[i];
s[i].clr();
tmp[i]=i;
}
rot=build(1,n,0);char opt[10];
while(m--){
scanf("%s%d%d",opt,&x,&k);
if(opt[0]=='M'){
a[x]=k;n++;s[n].d[0]=x+k;s[n].d[1]=x-k;s[n].clr();
Insert(rot,n,0,0);
}
else printf("%d\n",query(rot,x+a[x]-k,x+a[x]+k,x-a[x]-k,x-a[x]+k));
}
return 0;
}