题意:
(稍微转化一下)每次加一些点,在一个正方形内查询点的个数。
题解:
先坐标旋转做成矩形查询,然后比较直观的是
KDtree+替罪羊暴力重建
。
Code:https://paste.ubuntu.com/26306229/
还有一种厉害的方法:分治。
比较明显的是可以CDQ分治+ 主席树,另外还可以对这些点对做二进制分组。每次暴力重建的复杂度为
nlogn
,总的复杂度为
O(nlog2n)
后者不仅可以强制在线,而且比较好写,缺点是所占空间很大,如果不加以回收会达到
O(nlog2n)
。
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
char ch=getchar();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
inline void W(int x){
static int buf[50];
if(!x){putchar('0');return;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0])putchar(buf[buf[0]--]+'0');
}
const int N=1e5+50,base=1e5+1,R=4e5+4,LIM=20,INF=0x3f3f3f3f,_T=N-2;
struct P{
int x,y;
P(int x=0,int y=0):x(x),y(y){}
}p[N];
struct node{
node *lc,*rc;
int sze;
}Pool[N*120],*pool=Pool,*rt[N*120],*rt_null;
int n,q,a[N],sze[LIM],bnum;
inline node* newnode(){
node *t=++pool;
t->lc=(t->rc=NULL);
t->sze=0;
return t;
}
vector<int>con[LIM];
inline bool cmp_p(const int &a,const int &b){
return p[a].x<p[b].x||(p[a].x==p[b].x&&p[a].y<p[b].y);
}
inline void build(node *&x,int l,int r){
x=newnode();
if(l==r)return;
int mid=(l+r)>>1;
build(x->lc,l,mid);
build(x->rc,mid+1,r);
}
inline void insert(node *x,node *&y,int l,int r,int pos){
y=newnode();y->sze=x->sze+1;
y->lc=x->lc;y->rc=x->rc;
if(l==r)return;
int mid=(l+r)>>1;
(pos<=mid)?
(insert(x->lc,y->lc,l,mid,pos)):
(insert(x->rc,y->rc,mid+1,r,pos));
}
inline void rebuild(int c){
con[c].clear();
int bg=sze[c]-(sze[c]&(-sze[c]))+1;
for(int i=bg;i<=sze[c];++i)con[c].push_back(i);
sort(con[c].begin(),con[c].end(),cmp_p);
insert(rt_null,rt[*con[c].begin()],1,R,p[*con[c].begin()].y);
for(int i=1;i<con[c].size();++i)
insert(rt[con[c][i-1]],rt[con[c][i]],1,R,p[con[c][i]].y);
}
int xc1,yc1,xc2,yc2;
inline int query(node *x,node *y,int l,int r,int L,int R){
if(L<=l&&r<=R)return y->sze-x->sze;
int mid=(l+r)>>1;
if(R<=mid)return query(x->lc,y->lc,l,mid,L,R);
else if(L>mid)return query(x->rc,y->rc,mid+1,r,L,R);
else return query(x->lc,y->lc,l,mid,L,R)+query(x->rc,y->rc,mid+1,r,L,R);
}
inline int query(int c){
p[_T]=P(xc2+1,-INF);
int p1=lower_bound(con[c].begin(),con[c].end(),_T,cmp_p)-con[c].begin();
if(!p1)return 0;
p[_T]=P(xc1,-INF);
int p2=lower_bound(con[c].begin(),con[c].end(),_T,cmp_p)-con[c].begin();
return query(p2?(rt[con[c][p2-1]]):rt_null,rt[con[c][p1-1]],1,R,yc1,yc2);
}
int main(){
n=rd(),q=rd();
build(rt_null,1,R);
for(int i=1;i<=n;i++){
a[i]=rd();
p[i]=P(i-a[i]+base,i+a[i]+base);
}
for(int i=LIM;i>=0;i--)
if(n&(1<<i))
sze[++bnum]=(1<<i);
for(int i=1;i<=bnum;i++)sze[i]+=sze[i-1];
for(int i=1;i<=bnum;i++)rebuild(i);
for(int i=1;i<=q;i++){
static char op[10];
scanf("%s",op+1);
if(op[1]=='Q'){
int x=rd(),k=rd();
xc1=x-a[x]+k+base;xc2=x-a[x]-k+base;
yc1=x+a[x]+k+base;yc2=x+a[x]-k+base;
(xc1>xc2)&&(swap(xc1,xc2),0);
(yc1>yc2)&&(swap(yc1,yc2),0);
int ans=0;
for(int c=1;c<=bnum;++c)
ans+=query(c);
W(ans);putchar('\n');
}else{
int x=rd(),y=rd();a[x]=y;
p[++n]=P(x-y+base,x+y+base);
int lst=1;
while(bnum&&(sze[bnum]&(-sze[bnum]))==lst){
--bnum;lst<<=1;
}
sze[++bnum]=lst;
sze[bnum]+=sze[bnum-1];
rebuild(bnum);
}
}
}