该题很显然可以发现是一个动态的,如果使用普通差分显然会超时,所以需要实时更新的数据结构这里我们选择二维的树状数组(您要是要用二维线段树我也没啥意见),我们预处理一下,可以在得到右上坐标的同时以O(1)的时间获得左下坐标。随后我们需要考虑的便是配对问题,相对于普通差分,我们会在一个数组里面设置一个起始值,一个终止值,可是这样我们便无法讲起始值和终止值区分开,所以我们需要采用两个树状数组对应进行匹配。其次对于二维向量匹配问题,我们只需要一个起始向量,但是想固定一个矩阵,我们需要3个终止向量,注意的是需要让一个起始向量配对3个终止向量,所以我们可以将向量分为一个二维向量信息,即水平向量信息,竖直向量信息。终止信息分为3种,单水平向量信息,单竖直向量信息,即有水平向量信息又有竖直向量信息。然后在配对期间我们采用差分配对的方法进行配对,计算信号数差即可。
#include<bits/stdc++.h>
using namespace std;
const int N=2e3+7;
struct xyz{
int x,y,z;
inline xyz operator + (const xyz &a)const{
return {x+a.x,y+a.y,z+a.z};
}
inline xyz operator - (const xyz &a)const{
return {x-a.x,y-a.y,z-a.z};
}
};
xyz tr1[N][N],tr2[N][N];
int su[N],vis[N];
int lowit(int x){
return x&-x;
}
int read(){
int x=0;char ch;
for(ch=getchar();!isdigit(ch);ch=getchar());
for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x;
}
void ptr(int x){
if(x>9)ptr(x/10);
putchar(x%10+'0');
}
void oula(){
vis[1]=1;
for(int i=2;i<N;i++){
if(!vis[i])vis[i]=1,su[++su[0]]=i;
for(int j=1;j<=su[0]&&i*su[j]<N;j++){
vis[i*su[j]]=i;
if(i%su[j]==0)break;
}
}
}
void add(xyz t[N][N],int x,int y,xyz c){
for(int a=x;a<N;a+=lowit(a))
for(int b=y;b<N;b+=lowit(b))
t[a][b]=t[a][b]+c;
}
xyz sum(xyz t[N][N],int x,int y){
xyz res={0,0,0};
for(int a=x;a;a-=lowit(a))
for(int b=y;b;b-=lowit(b))
res=res+t[a][b];
return res;
}
int main(){
oula();
int m=read();
while(m--){
int k=read(),x,y,x2=read(),y2=read();
if(k==1){
x=vis[x2];y=vis[y2];
add(tr1,x,y,{0,0,1});add(tr2,x2,y2,{0,0,1});add(tr2,x,y2,{0,1,0});add(tr2,x2,y,{1,0,0});
}
else{
x=read(),y=read();
int res=sum(tr1,x,y).z;
int res1=sum(tr2,x,y2-1).y+sum(tr2,x2-1,y).x-sum(tr2,x2-1,y2-1).z;
//cout<<res-res1<<"\n";
ptr(res-res1);putchar('\n');
}
}
}
京公网安备 11010502036488号