ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2020 ICPC 上海站(gym 102900) 题解

2021-01-17 23:33:57  阅读:227  来源: 互联网

标签:上海站 ch min int 题解 gym need LL define


2020 ICPC 上海站(gym 102900) 题解

Problem H Rice Arrangement

这题相对而言比较简单。

假设我们直到了每一碗饭能分给的人的区间,然后就可以发现,将这些区间排出来一定是这样:

[-------]-----
--[-------]---
-----[-------]

也就是右端点随左端点递增而递增。

如果我们将饭和人链接一条线。

大概是这样:

o----o------o-----o
|     \    /     /
x------x---x---x---

可以发现不可能出现这样的情况:

o-o--------
 V
/ \  
x---x------

由于覆盖的人可以看作区间。

所以确定了第一个人吃哪一碗饭,其它的都确定了。

我们先假设所有的都想左转,然后将度数排序。可以发现一定是一段后缀向右转。

时间复杂度为\(O(N^2\log N)\)

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
int n,t;
int Q;
int a[1001],b[1001];
int dist(int A,int B){
	if(A<=B) return B-A;
	return n-A+B;
}
void solve(){
	scanf("%d%d",&n,&t);
	rep(i,t) scanf("%d",&a[i]);
	rep(i,t) scanf("%d",&b[i]);
	sort(a,a+t);
	sort(b,b+t);
	int ret=INF;
	rep(i,t)
	{
		vector<int> v;
		rep(j,t){
			v.PB(dist(b[(i+j)%t],a[j]));
		}
		sort(ALL(v));
		int tmp=min(v[t-1],n-v[0]);
		rep(j,t-1){
			check_min(tmp,min(v[j]+v[j]+n-v[j+1],v[j]+2*n-v[j+1]-v[j+1]));
		}
		check_min(ret,tmp);
	}
	printf("%d\n",ret);
}
int main(){
	scanf("%d",&Q);
	while(Q--) solve();
	return 0;
}

Problem L Traveling in the Grid World

考虑这题的加强:

\[T\leq 1e6,n,m\leq 1e18 \]

也就是要\(O(1)\)回答询问。

首先可以发现如果\((n,m)=1\)则一步到达。

否则我们只需要走最近的折线就一定不会存在格点。可以证明最优折线和对角线形成的三角形及其内部不存在格点,否则可以调整法变成更优答案。

然后原问题就可以迎刃而解了,只要枚举横坐标,然后选择最靠近对角线的点就可以了,时间复杂度为\(O(N)\)。

但是这题可以做到更优。

设\(x,y=n/(n,,m),m/(n,m)\)。

一个结论:
靠对角线最近的格点中最靠近中点的最优。

根据叉积的定义:

就是这个值最小的点(a,b):

\[x*b-y*m/(\sqrt {x^2+y^2}) \]

后面的那个是常数,不用管,前面的那个最小值为\(1\),直接exgcd求解就可以了。

可以发现,所有距离\(> 1/(\sqrt{x^2+y^2})\)的至少为那个距离的两倍。

根据中位线可以发现一定存在格点,所以距离最近的中最靠近中间的最优。

code:

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
int T;
LL exGcd(LL a,LL b,LL &x,LL &y)
{
    if(b==0)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL r = exGcd(b,a%b,x,y);
    LL t = x; x = y;
    y = t-a/b*y;
    return r;
}
double dist(int x,int y){
	double tmp=1ll*x*x+1ll*y*y;
	return sqrt(tmp);
}
void solve(){
	int x,y;
	scanf("%d%d",&x,&y);
	if(__gcd(x,y)==1){
		printf("%.10f\n",dist(x,y));
		return;
	}
	int g=__gcd(x,y);
	int n=x,m=y;
	x=n/g;
	y=m/g;
	LL a,b;
	exGcd(x,y,b,a);
	a=-a;
	LL need=max(0ll,max((x-a)/x,(y-b)/y));
	a+=need*x;
	b+=need*y;
	need=min((a-1)/x,(b-1)/y);
	a-=need*x;
	b-=need*y;
	double rest=1e18;
	LL can=min((n-a)/x,(m-b)/y);
	can/=2;
	for(LL i=can-5;i<=can+5;++i){
		LL xx,yy;
		xx=a;
		yy=b;
		xx+=x*i;
		yy+=y*i;
		if(xx>=0&&yy>=0&&xx<=n&&yy<=m){
			check_min(rest,dist(xx,yy)+dist(n-xx,m-yy));
		}
	}
	printf("%.10f\n",rest);
}
int main(){
	scanf("%d",&T);
	while(T--) solve();	
	return 0;
}

标签:上海站,ch,min,int,题解,gym,need,LL,define
来源: https://www.cnblogs.com/gary-2005/p/14290780.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有