【BZOJ】【P1935】【Shoi2007】【Tree 园丁的烦恼】【题解】【树状数组+离散化】

传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1935

经典的问题,求一个点右下方的点的个数,x排序,y坐标离散后树状数组,xtt大爷曾经讲过n维偏序,跟我们说:"一维排序、二维数据结构、三维分治"

Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=500010;
int n,m;
int d[maxn];
int lowbit(int x){return x&-x;}
void updata(int x){
	for(int i=x;i<maxn;i+=lowbit(i))d[i]++;
}
int get(int x){
	int ans=0;for(int i=x;i;i-=lowbit(i))ans+=d[i];return ans;
}
int getint(){
	int res=0;char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))(res*=10)+=ch-'0',ch=getchar();
	return res;
}
struct qes{
	int x,y,ind,f;
	bool operator<(const qes &a)const{
		return x<a.x||(x==a.x&&y<a.y)||(x==a.x&&y==a.y&&ind<a.ind);
	}
};
struct Point{
	int x,y;
	bool operator<(const Point &a)const{
		return x<a.x||(x==a.x&&y<a.y); 
	}
};
qes Q[maxn<<2];
int siz=0;
map<int,int>Y;
Point p[maxn];
int anss[maxn];
int main(){
	n=getint();m=getint();
	for(int i=1;i<=n;i++){
		p[i].x=getint()+1;
		p[i].y=getint()+1;
		Y[p[i].y]=1;
	}sort(p+1,p+1+n);
	for(int i=1;i<=m;i++){
		int x1=getint()+1,y1=getint()+1,x2=getint()+1,y2=getint()+1;
		Y[y1-1]=1;
		Y[y2]=1;
		siz++;
		Q[siz].x=x2;
		Q[siz].y=y2;
		Q[siz].ind=i;
		Q[siz].f=1*(x2>0&&y2>0);
		siz++;
		Q[siz].x=x2;
		Q[siz].y=y1-1;
		Q[siz].ind=i;
		Q[siz].f=-1*(x2>0&&y1-1>0);
		siz++;
		Q[siz].x=x1-1;
		Q[siz].y=y2;
		Q[siz].ind=i;
		Q[siz].f=-1*(x1-1>0&&y2>0);
		siz++;
		Q[siz].x=x1-1;
		Q[siz].y=y1-1;
		Q[siz].ind=i;
		Q[siz].f=1*(x1-1>0&&y1-1>0);		
	}sort(Q+1,Q+1+siz);
	int tot=0;
	for(map<int,int>::iterator it=Y.begin();it!=Y.end();it++)it->second=++tot;
	for(int i=1;i<=n;i++)p[i].y=Y[p[i].y];
	for(int i=1;i<=siz;i++)Q[i].y=Y[Q[i].y];
	int now=1;
	for(int i=1;i<siz;){
		do{
			if(Q[i].f)
			for(int &j=now;j<=n&&p[j].x<=Q[i].x;j++){
				updata(p[j].y);
			}anss[Q[i].ind]+=Q[i].f*(get(Q[i].y));i++;
		}while(i<siz&&Q[i].f&&Q[i].x!=Q[i+1].x);
	}for(int &j=now;j<=n&&p[j].x<=Q[siz].x;j++){
		updata(p[j].y);
	}anss[Q[siz].ind]+=Q[siz].f*(get(Q[siz].y));
	for(int i=1;i<=m;i++)
	printf("%d\n",anss[i]);
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值