Description
Input
Output
对于每次询问操作,输出一个非负整数表示答案
Sample Input
2 4 3
Query 2 2
Modify 1 3
Query 2 2
Modify 1 2
Query 1 1
Sample Output
3
3
Solution
设一个点的坐标为$(x,a[x])$,然后发现$graze(x,i) \leq k$的点就是曼哈顿距离到$x$点距离小于等于$k$的点。
但这玩意儿好像是个斜着的正方形?咋矩形求和啊……话说我是不是之前做$K-D~Tree$的时候看过一个什么曼哈顿转切比雪夫的?
曼哈顿$(x,a[x])->$切比雪夫$(x+a[x],x-a[x])$,切比雪夫计算两点距离好像是横纵坐标差的$max$?
这样转下切比雪夫然后一个点要查询的点不就成了一个正着的正方形内的点的个数了么……
这样好像就可以矩形求和了啊……发现那个什么鬼畜历史版本就是扯淡?不就是加入一个点么…
$PS:$此题数据范围描述是假的!
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define N (1000009) 5 using namespace std; 6 7 struct Que{int x,y,opt,v;}Q[N],tmp[N]; 8 int n,m,q_num,cnt,a[N],c[N],ans[N]; 9 char opt[10]; 10 11 inline int read() 12 { 13 int x=0,w=1; char c=getchar(); 14 while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();} 15 while (c>='0' && c<='9') x=x*10+c-'0', c=getchar(); 16 return x*w; 17 } 18 19 void Update(int x,int k) 20 { 21 for (; x<=1e6; x+=(x&-x)) c[x]+=k; 22 } 23 24 int Query(int x) 25 { 26 int ans=0; 27 for (; x; x-=(x&-x)) ans+=c[x]; 28 return ans; 29 } 30 31 void CDQ(int l,int r) 32 { 33 if (l==r) return; 34 int mid=(l+r)>>1; 35 CDQ(l,mid); CDQ(mid+1,r); 36 int i=l,j=mid+1,k=l-1; 37 while (i<=mid || j<=r) 38 if (j>r || i<=mid && (Q[i].x<Q[j].x || Q[i].x==Q[j].x && Q[i].opt<Q[j].opt)) 39 { 40 if (Q[i].opt==1) Update(Q[i].y,1); 41 tmp[++k]=Q[i]; ++i; 42 } 43 else 44 { 45 if (Q[j].opt==2) 46 { 47 if (Q[j].v>0) ans[Q[j].v]+=Query(Q[j].y); 48 else ans[-Q[j].v]-=Query(Q[j].y); 49 } 50 tmp[++k]=Q[j]; ++j; 51 } 52 for (int i=l; i<=mid; ++i) if (Q[i].opt==1) Update(Q[i].y,-1); 53 for (int i=l; i<=r; ++i) Q[i]=tmp[i]; 54 } 55 56 int main() 57 { 58 n=read(); m=read(); 59 for (int i=1; i<=n; ++i) 60 { 61 a[i]=read(); 62 Q[++q_num]=(Que){i+a[i],i-a[i],1,1}; 63 } 64 for (int i=1; i<=m; ++i) 65 { 66 scanf("%s",opt); int x=read(),k=read(); 67 if (opt[0]=='M') a[x]=k, Q[++q_num]=(Que){x+k,x-k,1,1}; 68 else 69 { 70 ++cnt; 71 Q[++q_num]=(Que){x+a[x]+k,x-a[x]+k,2,cnt}; 72 Q[++q_num]=(Que){x+a[x]-k-1,x-a[x]-k-1,2,cnt}; 73 Q[++q_num]=(Que){x+a[x]-k-1,x-a[x]+k,2,-cnt}; 74 Q[++q_num]=(Que){x+a[x]+k,x-a[x]-k-1,2,-cnt}; 75 } 76 } 77 for (int i=1; i<=q_num; ++i) Q[i].x+=500000, Q[i].y+=500000; 78 CDQ(1,q_num); 79 for (int i=1; i<=cnt; ++i) printf("%d\n",ans[i]); 80 }