题解:树状数组或k-d树。
树状数组:
将数据离散化后将询问拆成左x和右x。依次加入点查询即可。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int Maxn=3e5+50;
inline int read()
{
char ch=getchar();int i=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}
return i*f;
}
int n,m,x[Maxn],y[Maxn],totx,toty,tot,mx,my;
ll Bt[Maxn],ans[Maxn];
inline int lowbit(int x)
{
return x&(-x);
}
inline void ins(int x,ll val)
{
while(x<=mx)
{
Bt[x]+=val;
x+=lowbit(x);
}
}
inline ll get(int x)
{
ll res=0;
while(x>0)
{
res+=Bt[x];
x-=lowbit(x);
}
return res;
}
struct point
{
int x,y;
ll pw;
}p[Maxn];
struct query
{
int x1,y1,x2,y2;
}que[Maxn];
struct handle
{
int x,pos,isque,cb;
handle(){}
handle(int x,int pos,int isque,int cb):x(x),pos(pos),isque(isque),cb(cb){}
friend inline bool operator <(const handle &a,const handle &b)
{
if(a.x!=b.x)return a.x<b.x;
else return a.isque<b.isque;
}
}hd[Maxn];
inline void l_b()
{
sort(x+1,x+totx+1);
sort(y+1,y+toty+1);
mx=unique(x+1,x+totx+1)-x-1;
my=unique(y+1,y+toty+1)-y-1;
for(int i=1;i<=n;i++)
{
p[i].x=lower_bound(x+1,x+mx+1,p[i].x)-x;
p[i].y=lower_bound(y+1,y+my+1,p[i].y)-y;
}
for(int i=1;i<=m;i++)
{
que[i].x1=lower_bound(x+1,x+mx+1,que[i].x1)-x;
que[i].x2=lower_bound(x+1,x+mx+1,que[i].x2)-x;
que[i].y1=lower_bound(y+1,y+mx+1,que[i].y1)-y;
que[i].y2=lower_bound(y+1,y+mx+1,que[i].y2)-y;
}
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
{
p[i].x=read(),p[i].y=read(),p[i].pw=read();
x[++totx]=p[i].x;y[++toty]=p[i].y;
}
for(int i=1;i<=m;i++)
{
que[i].x1=read();
x[++totx]=que[i].x1;
que[i].y1=read();
y[++toty]=que[i].y1;
que[i].x2=read();
x[++totx]=que[i].x2;
que[i].y2=read();
y[++toty]=que[i].y2;
}
l_b();
for(int i=1;i<=n;i++)
{
hd[++tot]=handle(p[i].x,i,0,0);
}
for(int i=1;i<=m;i++)
{
hd[++tot]=handle(que[i].x1-1,i,1,-1);
hd[++tot]=handle(que[i].x2,i,1,1);
}
sort(hd+1,hd+tot+1);
for(int i=1;i<=tot;i++)
{
if(hd[i].isque)ans[hd[i].pos]+=((get(que[hd[i].pos].y2)-get(que[hd[i].pos].y1-1))*hd[i].cb);
else ins(p[hd[i].pos].y,p[hd[i].pos].pw);
}
for(int i=1;i<=m;i++)
cout<<ans[i]<<endl;
}
k-d树:
裸题,但会被卡20分。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
const int Maxn=1e5+50;
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
inline ll read()
{
char ch=getchar();ll i=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
return i*f;
}
struct point
{
ll x,y,pw;
point(){}
point(ll x,ll y):x(x),y(y),pw(0){}
}p[Maxn];
struct node
{
node *lc,*rc;
point x;
ll mnx,mny,mxx,mxy,sum;
node():lc(NULL),rc(NULL){}
void upt()
{
if(lc)
{
mnx=min(mnx,lc->mnx);
mny=min(mny,lc->mny);
mxx=max(mxx,lc->mxx);
mxy=max(mxy,lc->mxy);
sum+=lc->sum;
}
if(rc)
{
mnx=min(mnx,rc->mnx);
mny=min(mny,rc->mny);
mxx=max(mxx,rc->mxx);
mxy=max(mxy,rc->mxy);
sum+=rc->sum;
}
}
}*rt,POOL[Maxn],*pool=POOL;
inline node* newnode(point x)
{
++pool;
pool->x=x;
pool->mnx=pool->mxx=x.x;
pool->mny=pool->mxy=x.y;
pool->sum=x.pw;
return pool;
}
int n,Q;
inline bool comx(const point &x,const point &y)
{
return x.x<y.x||(x.x==y.x&&x.y<y.y);
}
inline bool comy(const point &x,const point &y)
{
return x.y<y.y||(x.y==y.y&&x.x<y.x);
}
inline void build(node *&now,int l,int r,int dim)
{
if(l==r)
{
now=newnode(p[l]);
return;
}
int mid=(l+r)>>1;
if(!dim)nth_element(p+l,p+mid,p+r+1,comx);
else nth_element(p+l,p+mid,p+r+1,comy);
now=newnode(p[mid]);
if(mid>l)build(now->lc,l,mid-1,dim^1);
if(r>mid)build(now->rc,mid+1,r,dim^1);
now->upt();
return;
}
inline bool judgein(point x,ll mx1,ll my1,ll mx2,ll my2)
{
return (x.x>=mx1&&x.x<=mx2&&x.y>=my1&&x.y<=my2);
}
inline bool judgeinsert(node *x,ll mx1,ll my1,ll mx2,ll my2)
{
if(judgein(point(x->mnx,x->mny),mx1,my1,mx2,my2)||judgein(point(x->mnx,x->mxy),mx1,my1,mx2,my2)||judgein(point(x->mxx,x->mny),mx1,my1,mx2,my2)||judgein(point(x->mxx,x->mxy),mx1,my1,mx2,my2))return true;
if(judgein(point(mx1,my1),x->mnx,x->mny,x->mxx,x->mxy)||judgein(point(mx1,my2),x->mnx,x->mny,x->mxx,x->mxy)||judgein(point(mx2,my1),x->mnx,x->mny,x->mxx,x->mxy)||judgein(point(mx2,my2),x->mnx,x->mny,x->mxx,x->mxy))return true;
if(x->mnx<=mx1&&x->mxx>=mx2&&x->mny>=my1&&x->mxy<=my2)return true;
if(x->mnx>=mx1&&x->mxx<=mx2&&x->mxy>=my2&&x->mny<=my1)return true;
return false;
}
inline ll query(node *now,ll mx1,ll my1,ll mx2,ll my2)
{
if(now->mnx>=mx1&&now->mny>=my1&&now->mxx<=mx2&&now->mxy<=my2)return now->sum;
ll res=0;
if(now->lc&&judgeinsert(now->lc,mx1,my1,mx2,my2))res+=query(now->lc,mx1,my1,mx2,my2);
if(now->rc&&judgeinsert(now->rc,mx1,my1,mx2,my2))res+=query(now->rc,mx1,my1,mx2,my2);
if(judgein(now->x,mx1,my1,mx2,my2))res+=now->x.pw;
return res;
}
int main()
{
n=read(),Q=read();
for(int i=1;i<=n;i++)p[i].x=read(),p[i].y=read(),p[i].pw=read();
build(rt,1,n,0);
while(Q--)
{
ll mx1=read(),my1=read(),mx2=read(),my2=read();
cout<<query(rt,mx1,my1,mx2,my2)<<endl;
}
}