列表

详情


NC54306. 拉普兰德的愿望

描述

暴虐的恶人阻断正义的道路,我的主人啊,以复仇与恶意为名,引领弱小的人吧。

众所周知,拉普兰德对德克萨斯有特殊的感情。

让德克萨斯来担任队长!

把德克萨斯放到我的小队来!

哈哈哈,好,我喜欢你对我的信任。德克萨斯做得到吗?

拉普兰德知道德克萨斯喜欢吃Pocky
于是它跑遍了整个鲁珀族,终于买来了足够德克萨斯吃一辈子的Pocky!
但是德克萨斯并不想见拉普兰德。于是拉普兰德找了N个埋伏点,准备和德克萨斯来一个不期而遇。

但是拉普兰德很担心自己的计划会败露,他认为两个埋伏点如果距离小于d,则若一个被发现,另一个也会被发现。他想知道有多少对藏身之地之间的距离小于d,请你告诉他

在本题中,我们定义两点之间的距离为曼哈顿距离,即|X1-X2|+|Y1-Y2|,其中|x|表示x的绝对值


输入描述

第一行三个整数N,d,L,表示平面上有N个点,不安全距离为d,坐标的绝对值不超过L

接下来N行,每行两个整数xi,yi表示每个点的坐标

输出描述

第一行一个整数d,表示距离不小于d的点对的数量

示例1

输入:

5 4 10 
5 2 
7 2 
8 4 
6 5 
4 4 

输出:

5

说明:

符合条件的点对有:(1,3)(1,4)(2,4)(2,5)(3,5)

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 104ms, 内存消耗: 3616K, 提交时间: 2023-05-10 21:06:08

#include<bits/stdc++.h>
#define int long long
#define maxn 1000100
#define pii pair<int,int>
using namespace std;
int n,d,l,b[maxn];
pii p[maxn];
void add(int x,int w){
    while(x<maxn) b[x]+=w,x+=x&-x;
}
int query(int x){
   int res=0;
   while(x) res+=b[x],x-=x&-x;
   return res;
}
signed main(){
    cin>>n>>d>>l;
    for(int i=1;i<=n;i++){
        int x,y;
        cin>>x>>y;
        p[i].first=x+y+2*l+1;
        p[i].second=x-y+2*l+1;
    }
    sort(p+1,p+1+n);
    int j=1;
    int ans=0;
    for(int i=1;i<=n;i++){
        while(p[i].first-p[j].first>=d) add(p[j].second,-1),j++;
        ans+=query(min((long long )maxn,p[i].second+d-1))-query(max(0ll,p[i].second-d));
        add(p[i].second,1);
    }
    cout<<n*(n-1)/2-ans<<'\n';
}

C++14(g++5.4) 解法, 执行用时: 91ms, 内存消耗: 2028K, 提交时间: 2019-11-23 11:25:19

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
const int N=1e6+100;
const int fix=5e5+100;

int c[N];

void add(int x,int v)
{
	while(x<N){
		c[x]+=v;
		x+=x&-x;
	}
}
int query(int x){
	int ans=0;
	while(x)
	{
		ans+=c[x];
		x-=x&-x;
	}
	return ans;
}

struct node
{
	int x,y;
	bool operator<(const node &p) const
	{
		return x<p.x;
	};
}q[N];

int main()
{
	ll fk,n,d;
	cin>>n>>d>>fk;d--;
	for(int i=1;i<=n;i++)
	{
		int x,y;
		cin>>x>>y;
		q[i].x=x+y,q[i].y=x-y+fix;
	}
	sort(q+1,q+1+n);
	int j=1;
	ll ans=n*(n-1)/2;
	for(int i=1;i<=n;i++)
	{
		while(j<i&&q[i].x-q[j].x>d) add(q[j].y,-1),j++;
		ans-=query(q[i].y+d)-query(q[i].y-d-1);//减去不符合的 
		add(q[i].y,1);
	}
	cout<<ans<<endl;
	return 0;
}

C++ 解法, 执行用时: 67ms, 内存消耗: 16888K, 提交时间: 2022-07-13 22:00:00

#include<bits/stdc++.h>
using namespace std;

#define x first
#define y second
using pii = pair<int, int>;

const int N=2e6+50;

int n, d, L;
pii w[N];

int tr[N];

int lowbit(int x){
	return x&-x;
}

void add(int x, int k){
	for(; x<N; x+=lowbit(x)) tr[x]+=k;
}

int query(int x){
	int res=0;
	for(; x; x-=lowbit(x)) res+=tr[x];
	return res;
}

signed main(){
	cin>>n>>d>>L;
	d=min(d-1, 200000);
	for(int i=1; i<=n; i++){
		int x, y; scanf("%d %d", &x, &y);
		w[i]={x+y, x-y+L+N/4};
	}
	sort(w+1, w+1+n);
	
	long long res=1LL*n*(n-1)>>1;
	for(int i=1, j=1; i<=n; i++){
		while(j<i && w[i].x-w[j].x>d) add(w[j++].y, -1);
		res-=query(w[i].y+d)-query(w[i].y-d-1);
		add(w[i].y, 1);
	}
	cout<<res<<endl;
	return 0;
}

上一题