传送门:bzoj4170
题解
当我们知道可以把价值看成y坐标并把(x,y)的菱形转化为(x-y,x+y)的矩形来cdq时,这道题就成模板了。
真妙啊
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define mid ((l+r)>>1)
typedef long long ll;
using namespace std;
const int N=5e6+10;
const int M=6e4+10;
int cnt,n,Q,tot,MX,a[M];
ll ans[500010],tre[500010];//2.space 80000->500010
char s[15];
struct P{int v,x,y,id;}q[N],tp[N];
inline int max(int x,int y){return x>y?x:y;}
inline int rd()
{
char ch=getchar();int x=0,f=1;
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
inline void ad(int x,int v)
{for(;x<=MX && x!=0;x+=(x&(-x))) tre[x]+=v;}//x!=0
inline ll get(int x)
{ll ret=0;for(;x>0;x-=(x&(-x))) ret+=tre[x];return ret;}
void cdq(int l,int r)
{
if(l==r) return;
int i,j,L=l,R=mid+1;
cdq(l,mid);cdq(mid+1,r);
for(i=R,j=l;i<=r;i++){
for(;j<=mid && q[j].x<=q[i].x;j++) if(!q[j].v) ad(q[j].y,1);
if(q[i].v) ans[q[i].id]+=q[i].v*get(q[i].y);
}
for(i=l;i<=mid && q[i].x<=q[r].x;i++) if(!q[i].v) ad(q[i].y,-1);
for(i=l;i<=r;i++){
if((q[L].x<=q[R].x || R>r) && L<=mid) tp[i]=q[L++];
else tp[i]=q[R++];
}
for(i=l;i<=r;i++) q[i]=tp[i];
}
int main(){
int i,X,K;
n=rd();Q=rd();
for(i=1;i<=n;i++){a[i]=rd();q[++cnt].x=i-a[i];q[cnt].y=i+a[i];MX=max(MX,max(q[cnt].x,q[cnt].y));}
for(i=1;i<=Q;i++){
scanf("%s",s);X=rd();K=rd();
if(s[0]=='M'){q[++cnt].x=X-K;q[cnt].y=X+K;a[X]=K;MX=max(MX,max(q[cnt].x,q[cnt].y));}
else{
q[++cnt].x=X-a[X]+K;q[cnt].y=X+a[X]+K;q[cnt].v=1;q[cnt].id=++tot;
MX=max(MX,max(q[cnt].x,q[cnt].y));
q[++cnt].x=X-a[X]-K-1;q[cnt].y=X+a[X]+K;q[cnt].v=-1;q[cnt].id=tot;
if(X+a[X]>K+1){
q[++cnt].x=X-a[X]+K;q[cnt].y=X+a[X]-K-1;q[cnt].v=-1;q[cnt].id=tot;
q[++cnt].x=X-a[X]-K-1;q[cnt].y=X+a[X]-K-1;q[cnt].v=1;q[cnt].id=tot;
}
}
}MX++;
cdq(1,cnt);
for(i=1;i<=tot;i++) printf("%lld\n",ans[i]);
return 0;
}