博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

2020-2021 ACM-ICPC, Asia Seoul Regional Contest (G, L)


21.1.27 2020-2021 ACM-ICPC, Asia Seoul Regional Contest

CF GYM 102920

A是模拟,扔给神仙队友就完事了
没听讲题,I不会啊/kk


G. Mobile Robot √

\(Description\)
给定\(n\)个机器人及其位置\(p_i\),和一个数\(d\),你需要给每个机器人找一个新位置\(p'_i\)使得机器人从\(1\)\(n\)所在位置为公差为\(d\)的等差数列,求最小的\(\max_{i=1}^n|p_i-p'_i|\)
\(n\leq10^6\)

\(Solution\)
其实比较有意思。只要第一个位置\(x\)确定,其它位置即\(x\pm(i-1)d\),所以就是使\(\max|p_i-x\pm(i-1)d|=\max|(p_i\pm(i-1)d)-x|=\max|A_i-x|\)最小。\(x\)任取,显然\(\max A_i-\min A_i\)除以\(2\)即为答案。

注意整数即使只是除以\(2\),保留一位小数也会有精度误差。。(不是\(X.5\))所以要手动输出\(X.5\)
还有常数\(5\)是个int型变量输出要用%d。。(运算没问题,编译器旧点输出会有点问题)

//514ms	15700KB
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
typedef long long LL;
const int N=1e6+5;
const LL INF=1e17;

LL p[N];

inline LL read()
{
	LL now=0,f=1; char c=gc();
	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
	for(;isdigit(c);now=now*10+c-48,c=gc());
	return now*f;
}

int main()
{
	int n=read(); LL d=read(),A;
	for(int i=1; i<=n; ++i) p[i]=read();

	LL mn=INF,mx=-INF;
	for(int i=1; i<=n; ++i) A=p[i]-(i-1)*d, mn=std::min(mn,A), mx=std::max(mx,A);
	LL ans=mx-mn;

	mn=INF,mx=-INF;
	for(int i=1; i<=n; ++i) A=p[i]+(i-1)*d, mn=std::min(mn,A), mx=std::max(mx,A);
	ans=std::min(ans,mx-mn);
	printf("%lld.%lld\n",ans/2,ans%2?5ll:0ll);//%.1f不行! 常数输出时要保证是longlong。。
	

	return 0;
}

L. Two Buildings(分治 决策单调性)

\(Description\)
给定一个序列\(h_i\),求\(\max_{1\leq i<j\leq n}(h_i+h_j)*(j-i)\)
\(n\leq10^6\)

\(Solution\)
这种区间题考虑分治,如何求过\(mid\)的区间的答案。
可以发现对左边区间只有递增的\(h_i\)是有用的,同理右边区间只需要考虑递减的\(h_i\)
找出单调的这些\(h_i\)记为\(A_i\),然后考虑对左区间的每个\(A_i\)找到右边最优匹配的那个位置\(p_i\),那么\(p_i\)是单调增加的。(可以想象二维平面上两点构成的矩形面积,或者感性理解一下)
也就是满足决策单调性。分治换一种写法,先弄出整个序列的单调的\(h_i\)。然后直接暴力求出当前区间\(mid\)的最优匹配点\(p\),然后对\([l,mid-1]\)\([mid+1,r]\)区间再递归,其需考虑的决策范围为\([L,p]\)\([p,R]\)
每次复杂度\(O(决策范围)\),即每层\(O(n)\),每层会删\(1,2,4,...\)个元素所以是\(O(\log)\)层,复杂度\(O(n\log n)\)

//342ms	11700KB
#include <bits/stdc++.h>
#define pc putchar
#define gc() getchar()
typedef long long LL;
const int N=1e6+5;

int A1[N],A2[N],h[N];
LL Ans;

inline int read()
{
	int now=0,f=1; char c=gc();
	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
	for(;isdigit(c);now=now*10+c-48,c=gc());
	return now*f;
}
#define Calc(p) (1ll*(h[A1[mid]]+h[A2[p]])*(A2[p]-A1[mid]))
void Solve(int l1,int r1,int l2,int r2)
{
	if(l1>r1) return;
	int mid=l1+r1>>1,pos=l2;
	for(int i=l2+1; i<=r2; ++i)
		if(Calc(i)>Calc(pos)) pos=i;
	Ans=std::max(Ans,Calc(pos));
	Solve(l1,mid-1,pos,r2), Solve(mid+1,r1,l2,pos);
}

int main()
{
	int n=read();
	for(int i=1; i<=n; ++i) h[i]=read();
	int cnt1=1,cnt2=1; A1[1]=1, A2[1]=n;
	for(int i=2; i<=n; ++i)
		if(h[i]>h[A1[cnt1]]) A1[++cnt1]=i;
	for(int i=n-1; i; --i)
		if(h[i]>h[A2[cnt2]]) A2[++cnt2]=i;
	Solve(1,cnt1,1,cnt2), printf("%lld\n",Ans);

	return 0;
}

posted @ 2021-01-27 23:52  SovietPower  阅读(398)  评论(0编辑  收藏  举报