洛谷P4148 简单题
线段树+分块
对x轴分块,每个块和每一列维护个动态开点线段树
每次插入时插入到对应的列和块里
这样时空复杂度都高,发现对于子树大小为1的节点,可以存进lazy里
insert时遇到没开的点就放下lazy然后return,遇到lazy就pushdown
query的话不必pushdown,因为存在lazy的点下边就没东西了,判断是否在查询范围内然后乘上贡献return
#include<bits/stdc++.h>
using namespace std;
struct tree{
int lc,rc;
int sum;
int lazy;
}tre[(int)2e6];
int n,tot;
int size;
int root[(int)5e5+11],rot[711];
inline int read()
{
int s=0;
char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9')
{
s=(s<<1)+(s<<3)+(ch^48);
ch=getchar();
}
return s;
}
void pushdown(int i,int mid)
{
if(tre[i].lazy<=mid)
{
if(!tre[i].lc) tre[i].lc=++tot;
tre[tre[i].lc].sum=tre[i].sum;
tre[tre[i].lc].lazy=tre[i].lazy;
tre[i].lazy=0;
}
else
{
if(!tre[i].rc) tre[i].rc=++tot;
tre[tre[i].rc].sum=tre[i].sum;
tre[tre[i].rc].lazy=tre[i].lazy;
tre[i].lazy=0;
}
return;
}
void insert(int &i,int l,int r,int x,int val)
{
if(!i) {i=++tot;tre[i].lazy=x;tre[i].sum=val;return;};
if(tre[i].lazy)pushdown(i,(l+r)/2);tre[i].sum+=val;
if(l==r) return;
int mid=(l+r)>>1;
if(x<=mid) insert(tre[i].lc,l,mid,x,val);
else insert(tre[i].rc,mid+1,r,x,val);
return;
}
int query(int i,int l,int r,int x,int y)
{
if(tre[i].lazy) return (tre[i].lazy>=x&&tre[i].lazy<=y)*tre[i].sum;
if(!i) return 0;
if(l>=x&&r<=y) return tre[i].sum;
int mid=(l+r)>>1;
int ans=0;
if(x<=mid) ans+=query(tre[i].lc,l,mid,x,y);
if(y>mid) ans+=query(tre[i].rc,mid+1,r,x,y);
return ans;
}
int main()
{
n=read();
int ty,ans=0,l,r;
size=sqrt(n)*1.5+2;
int x,y,w;
int xp,yp,xd,yd,i;
while((ty=read())!=3)
{
ans=0;
if(ty==1)
{
x=read()^ans;
y=read()^ans;
w=read()^ans;
insert(root[y],1,n,x,w);
insert(rot[y/size+1],1,n,x,w);
}
else
{
xd=read()^ans,yd=read()^ans;
xp=read()^ans,yp=read()^ans;
ans=0;
l=yd/size+1;
r=yp/size+1;
if(l==r)
{
for(i=yd;i<=yp;i++) ans+=query(root[i],1,n,xd,xp);
printf("%d\n",ans);
continue;
}
for(i=yd;i/size+1==l;i++) ans+=query(root[i],1,n,xd,xp);
for(i=l+1;i<r;i++) ans+=query(rot[i],1,n,xd,xp);
for(i=yp;i/size+1==r;i--) ans+=query(root[i],1,n,xd,xp);
printf("%d\n",ans);
}
}
return 0;
}