Codeforces Round #812 (Div. 2)
作者:互联网
A. Traveling Salesman Problem
题意:空间中 在坐标轴上给几个点,问最后,从原点出发经过所有点,再返回原点所经过的最远距离
分析:
找到 最大的 x ,最小的 x ,最大的 y ,最小的 y ,然后根据 曼哈顿距离,计算一个大正方形的边长就可以了
为什么不能先把所有点初始化成无穷大?
因为如果只有一个点, (1,0) 这时候 最大的 x 和最小的 x 都是 1,但实际上最小的 x 应该是 0
void solve() { // cin>>n>>m; cin>>n; int mxx = 0,mxy = 0,mnx = 0,mny = 0; fo(i,1,n) { int x,y;cin>>x>>y; mxx = max(mxx,x); mxy = max(mxy,y); mnx = min(mnx,x); mny = min(mny,y); } cout<<(mxx - mnx) * 2 + (mxy - mny) * 2<<endl; }
B. Optimal Reduction
题意:一段长度为 n 的序列 a ,每次能使一段区间内的数 -1 ,问要最终使整个区间的所有数都变成 0 ,该序列 在该序列的排列中是不是操作次数最少的,如果是,输出Yes,否则No
分析:
如果整个区间是 一个 凸的形状,当然可以,但如果有一个 凹的形状,也就是有个极小值且不在边界上,就需要先把这个极小值左边的所有数变成0,再把这个极小值右边的数变成0
只要看看有没有一个先减小,再增加的位置就可以了
//#define int ll const int N = 1e5+10; int n,m; int a[N]; void solve() { cin>>n; ms(a,0); fo(i,1,n) cin>>a[i]; bool f = 0,ff = 0; fo(i,2,n-1) { if(a[i] < a[i-1]) f = 1;if(f && a[i] < a[i+1]) ff = 1; } if(ff) { NO; } else { YES; } }
C. Build Permutation
题意:给一个 n ,构造一个长度 为 n 的序列 ,使这个序列的所有数ai 和 它的位置 i 相加后 是一个平方数(开根号后不是小数)
分析:
从n-1 枚举到0,每个位置,取能取的最大值,比如 第 n - 1 个位置,首先取一个比 n - 1 更大的平方数 x ,如果 x == n - 1 + k , k < n 且未被取过的数
首先 n < 100000,这个范围内的平方数总共 317 个,且最后一个大于100000的数,i * i = 100489
且每个数之后的第一个平方数,最多比这个平方数大 一倍
所以直接对 (n - 1) * 2 取根号 再平方就是比这个数大的第一个平方数
比如 9999,直接从最大的平方数往下枚举到当前数 i 的根号数,每个数最多枚举 300次,总共 100000个数,时间复杂度远小于 3e8,没到一秒可以过
//#define int ll const int N = 1e5+10; int n,m,ans[N]; bool st[N];void solve() { cin>>n;ms(st,0); int lim = sqrt(2 * n - 2); of(i,n-1,0) { int s = sqrt(i); if(s * s != i) s ++ ; for(int j = lim;j >= s;j -- ) { if(j * j - i > n - 1 || st[j * j - i]) continue; st[j * j - i ] = 1; ans[i] = j * j - i; break; } } fo(i,0,n-1)cout<<ans[i]<<" \n"[i==n-1]; }
标签:平方,int,cin,Codeforces,序列,812,st,Div,fo 来源: https://www.cnblogs.com/er007/p/16636940.html