列表

详情


NC202248. 牛牛与星辰

描述

牛牛喜欢星辰,因为星星是他看她的眼睛。

如果几颗星星在一起,牛牛会感到兴奋。因为他觉得每颗星星都有自己的归宿,现在又到了白色相簿的季节,所以当三颗星星在一起的时候,作为白学家的牛牛会更开心。牛牛觉得如果三颗星星形成的面积在一个范围内,那么这三颗星星就可以形成一个白学三角形。

现在把天空看成一个笛卡尔坐标系(即二维直角坐标系),牛牛现在可以看到颗星星,他想知道可以有多少个白学三角形,一颗星星可以在不同的白学三角形里面。

输入描述

第一行一个整数表示天空中的星辰个数.

第二行两个整数表示当一个三角形的面积在时,那么这个三角形就是白学三角形.

接下来行每行两个整数表示一个星星的二维坐标.
数据保证不存在重点和三点共线.

输出描述

一个整数表示牛牛可以看到的白学三角形的个数.

示例1

输入:

3 
0 10
0 0
3 0
0 4

输出:

1

原站题解

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

C++14(g++5.4) 解法, 执行用时: 2785ms, 内存消耗: 106084K, 提交时间: 2020-02-22 12:13:39

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cassert>
using namespace std;
const int maxn=3010;
int n,cnt,to[maxn],ato[maxn];
long long L,R;
struct point{long long x,y;}po[maxn],now[maxn];
struct line {long long x,y;int id1,id2;}li[maxn*maxn];
inline bool cmp(point aa,point bb)
{
	if (aa.x==bb.x) return aa.y<bb.y;
return aa.x<bb.x;
}
inline bool cmp1(line aa,line bb){return aa.x*bb.y-aa.y*bb.x>0;}
long long A(point a,point b,point c)
{
	long long x1=a.x-b.x,y1=a.y-b.y,x2=c.x-b.x,y2=c.y-b.y;
return abs(x2*y1-x1*y2);
}
long long solve(long long S)
{
	long long ans=0;
	for (int i=1;i<=n;i++) now[i]=po[i],to[i]=i,ato[i]=i;
	for (int i=1;i<=cnt;i++)
	{
		int s=ato[li[i].id1],e=ato[li[i].id2];
		//printf("lalal %d %d %d\n",i,s,e);
		if (s>=e) assert(0);
		int l=1,r=s-1,lc=s;
		while (l<=r)
		{
			int mid=(l+r)>>1;
			if (A(now[to[mid]],now[to[s]],now[to[e]])<=S) {lc=min(lc,mid); r=mid-1;}else l=mid+1;
		}
		ans+=s-lc;
		l=e+1; r=n; lc=e;
		while (l<=r)
		{
			int mid=(l+r)>>1;
			if (A(now[to[s]],now[to[e]],now[to[mid]])<=S) {lc=max(lc,mid); l=mid+1;}else r=mid-1;
		}
		ans+=lc-e;
		swap(to[s],to[e]);
		swap(ato[li[i].id1],ato[li[i].id2]);
		//for (int i=1;i<=n;i++) printf("%d ",to[i]);
		//printf("\n");
		//printf("%d %lld\n",i,ans);
	}
return ans;
}
int main()
{
	scanf("%d%lld%lld",&n,&L,&R);
	for (int i=1;i<=n;i++) scanf("%lld%lld",&po[i].x,&po[i].y);
	sort(po+1,po+n+1,cmp);
	//for (int i=1;i<=n;i++) printf("point%d: %lld %lld\n",i,po[i].x,po[i].y);
	for (int i=1;i<=n;i++)
	 for (int j=i+1;j<=n;j++)
	  li[++cnt]={po[j].x-po[i].x,po[j].y-po[i].y,i,j};
	sort(li+1,li+cnt+1,cmp1);
	//for (int i=1;i<=cnt;i++) 
	//printf("line%d: %lld %lld (%d->%d)\n",i,li[i].x,li[i].y,li[i].id1,li[i].id2);
	printf("%lld\n",(solve(2*R)-solve(2*L-1))/3);
return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 3235ms, 内存消耗: 70892K, 提交时间: 2020-03-09 11:49:15

#include <bits/stdc++.h>
using namespace std;
const int N=3e3+7,M=5e6+7;
int n,k,x[N],y[N],a[N],id[N]; long long l,r;
struct node{
    int a,b,id1,id2;
}e[M];
struct note{
    int a,b;
}f[N];
inline bool tmp(note a,note b){
    if(a.a==b.a) return a.b>b.b; return a.a>b.a;
}
inline long long getsum(node a,node b){
	return 1ll*a.a*b.b-1ll*a.b*b.a;
}
inline bool cmp(node a,node b){
	return (getsum(a,b)>0);
//	return atan2(a.b,a.a)<atan2(b.b,b.a);
}
inline long long getans(int a,int b,int c){
    return abs(1ll*(f[a].a-f[c].a)*(f[b].b-f[c].b)-1ll*(f[b].a-f[c].a)*(f[a].b-f[c].b));
}
inline long long solve(long long u){
    if(u<=0) return 0; long long ans=0;
    for(int i=1;i<=n;i++) a[i]=id[i]=i;
    for(int i=1;i<=k;i++){
        int x=e[i].id1,y=e[i].id2; if(a[x]>a[y]) swap(x,y);
        int l=1,r=a[x]-1,p=a[x];
        while(l<=r){
            int d=(l+r)>>1;
            if(getans(id[d],x,y)<=u) p=d,r=d-1; else l=d+1;
        }
        ans=ans+a[x]-p;
        l=a[y]+1,r=n,p=a[y];
        while(l<=r){
            int d=(l+r)>>1;
            if(getans(id[d],x,y)<=u) p=d,l=d+1; else r=d-1;
        }
        ans=ans+p-a[y];
        swap(a[x],a[y]),swap(id[a[x]],id[a[y]]);
    }
    return ans/3;
}
int main(){
    cin>>n>>l>>r,l=l*2-1,r=r*2;
    for(int i=1;i<=n;i++) scanf("%d%d",&f[i].a,&f[i].b); sort(f+1,f+n+1,tmp);
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            k++,e[k].a=f[i].a-f[j].a,e[k].b=f[i].b-f[j].b,e[k].id1=i,e[k].id2=j;
    sort(e+1,e+k+1,cmp);
    cout<<solve(r)-solve(l)<<endl;
    return 0;
}

上一题