1 条题解

  • 0
    @ 2025-8-24 22:27:24

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar KohaD_SEGA
    欢迎游玩舞萌DX

    搬运于2025-08-24 22:27:24,当前版本为作者最后更新于2023-10-07 23:59:15,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这个题是波罗的海 20042004 年信息竞赛的题目,放到现在应该是一道普及 + 的题目。

    我们来看看 n=1n=1 时的情形。例如, xmax=ymax=11,x_{\mathrm{max}}=y_{\mathrm{max}}=11, 矩形左下角和右上角分别为 (4,2), (5,7)(4,2),\ (5,7) 时,我们来直观地看一下哪些边界点是满足它和原点的连线与矩形相交的。

    这意味着我们只需考虑矩形的左上顶点和右下顶点,将原点与此二顶点相连的射线与边界交于两点,这两点之间的边界点中的整点即为我们所求的 n=1n=1 时的点。

    则题目变成:给定 nn 个区间,求一个整点,使得任何其他的点所被包括的区间数量均不大于该整点。这即是一道较低难度的模板题了。

    #include <bits/stdc++.h>
    using namespace std;
    struct el // 区间
    {
    	int h;//区间的整点边界
    	int tp;//是区间左界还是右界
    }m[20001];//区间有两个界,所以是10000*2
    struct ju//矩形
    {
    	int x_1;
    	int y_1;
    	int x_2;
    	int y_2;
    }mas[10001];
    int len,pried;
    int maxx,maxy,n;
    inline bool cmp(el A,el B)//排序
    {
    	if(A.h==B.h)	return A.tp>B.tp;
    	else return A.h<B.h;
    }
    #define QKSORT(l,r)	sort(m+(l),m+(r),cmp)
    inline void add(int x,int y,int tp)
    {
    	double a;
    	m[++len].tp=tp;
    	if(x*1LL*maxy<=y*1LL*maxx)	m[len].h=maxy;//只考虑外边界矩形的某一边
    	else
    	{
    		a=(long long)maxx*1LL*y;
    		a=a*1.0/x;
    		if(tp>0)	m[len].h=ceil(a-0.0001);//防止奇怪的浮点数出错
    		else	m[len].h=floor(a+0.0001);
    	}
    }
    int sum(int* x,int* y)
    {
    	int k,mx,mxh;
    	len=0;
    	for(int i=1;i<=n;i++)
    	{
    		if((long long)1LL*mas[i].x_1*maxy<1LL*mas[i].y_1*maxx)	continue;//它属于另外一边
    		add(mas[i].x_1,mas[i].y_1,1);
    		add(mas[i].x_2,mas[i].y_2,-1);
    	}
    	if(len>0)	QKSORT(1,len);
    	k=0,mx=0,mxh=0;
    	for(int i=1;i<=len;i++)
    	{
    		k+=m[i].tp;
    		if(k>mx)	mx=k,mxh=m[i].h;
    	}
    	*x=maxx,*y=mxh;
    	return mx;
    }
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin>>maxx>>maxy>>n;
    	int tmp=0,i=1;
    	for(int j=1;j<=n;j++)
    	{
    		cin>>mas[i].x_1>>mas[i].y_1>>mas[i].x_2>>mas[i].y_2;
    		if(mas[i].x_1==0 && mas[i].y_1==0)
    			pried++;
    		else
    		{
    			swap(mas[i].x_1,mas[i].x_2);
    			i++,tmp++;			
    		}
    	}
    	n=tmp;
    	int ats,ax=0,ay=0,bx=0,by=0;
    	ats=sum(&ax,&ay);
    	swap(maxx,maxy);//全部取反,考虑另一边
    	for(int i=1;i<=n;i++)
    	{
    		swap(mas[i].x_1,mas[i].y_1);
    		swap(mas[i].x_2,mas[i].y_2);
    		swap(mas[i].x_1,mas[i].x_2);
    		swap(mas[i].y_1,mas[i].y_2);
    	}
    	tmp=sum(&by,&bx);
    	if(ats<tmp)	ats=tmp,ax=bx,ay=by;//合并两边,得到答案
    	cout<<ats+pried<<' '<<ax<<' '<<ay<<endl;
    	return 0;
    }
    
    • 1

    信息

    ID
    5778
    时间
    1000ms
    内存
    128MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者