双倍经验题~2333
这道题的modify其实就是加点。。
有两种思路
一种是把它当成曼哈顿距离 那就是一个菱形区域 再把它转一下就是一个矩形 接着加上时间限制就是三个限制 三位偏序 嗯。。(我比较蠢 不会这种)
另一种就是列不等式 分类讨论~
合并一下
同理也搞一下(2)(3)就得出两个限制
加上时间 也是一样的三位偏序
代码有点丑。。。QAQ
#include<bits/stdc++.h>
using namespace std;
const int N=150002,M=200000;
inline int read()
{
char ch=getchar(); int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
return x*f;
}
struct node{int x,y,i,k;}p[N],a[N],b[N];
bool Cmp(node x1,node x2){return x1.x<x2.x;}
int ans[N],t[M*2+2],n;
void add(int x,int u){for(;x<=M*2;x+=x&-x)t[x]+=u;}
int query(int x){int s=0; for(;x;x-=x&-x)s+=t[x]; return s;}
void solve(int l,int r)
{
if(l==r)return;
int i,j,mid=(l+r)>>1,al=0,bl=0;
for(i=l;i<=mid;i++) if(!p[i].i) a[++al]=p[i];
for(i=mid+1;i<=r;i++) if(p[i].i)
{
b[++bl]=p[i],b[bl].i=i;
b[bl].x=p[i].x+p[i].k;
b[++bl]=p[i],b[bl].i=-i;
b[bl].x=p[i].x-p[i].k-1;
}
sort(a+1,a+1+al,Cmp);
sort(b+1,b+1+bl,Cmp);
for(j=i=1;i<=bl;i++)
{
while(a[j].x<=b[i].x && j<=al)
add(a[j].y+M,1),j++;
int u=query(min(b[i].y+b[i].k+M,M<<1))-query(max(0,b[i].y-b[i].k+M-1));
if(b[i].i>0) ans[b[i].i]+=u;
else ans[-b[i].i]-=u;
}
for(j=j-1;j;j--) add(a[j].y+M,-1);
solve(l,mid),solve(mid+1,r);
}
char c[15]; int h[N];
int main()
{
int i,x,y,n=read(),m=read(),q=0;
for(i=1;i<=n;i++)
{
h[i]=x=read();
p[++q]=(node){i-x,i+x,0,0};
}
for(i=1;i<=m;i++)
{
scanf("%s",c); x=read(),y=read();
if(c[0]=='Q')p[++q]=(node){x-h[x],x+h[x],1,y};
else h[x]=y,p[++q]=(node){x-h[x],x+h[x],0,0};
}
solve(1,q);
for(i=1;i<=q;i++)if(p[i].i)printf("%d\n",ans[i]);
return 0;
}