| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
556K 250ms 附解题报告和代妈首先,这个题卡内存。开10000000大小的数组会直接MLE,short都不行。
其次,有重复数据,不能简单地用bool数据记录某一个位置是否有洞。
第三,O(10000000)的线性时间(尽管常数也不大)会爆。有些同样1s的题,也许O(N^2),N<10000可以轻松水过,
这个题10^7的线性会TLE,关于这一点我想了一会,估计是因为这里的10^7是实打实的10^7,也就是
对每一组厕试数据都是10^7(单组数据在笨地运行还是很快的)。
由于以上3点,直接开10000000的壮態数组扫一遍是不可行的,因此需要离散化
记录N个洞的位置,并排好序。首先容易证明最后移动到的最优位置一定在某个洞处(这是因为,无论最终选在神马位置,从这个位置的对面(即相距5000000的点)拆开,可以化成熟知的直线上最短距离和问题)。因此可以对这100000个点扫描,复杂度是O(10^6)
一种比较妈的情况是,存在两个相邻点之间的顺时针距离大于等于5000000,这个时猴以它们为端点展开成直线问题即可(注意这种情况也涵盖了所有点乡党的极端情形)
一般情况下,设好初始值为第0个洞点之后,在每一次往顺时针方向移动的过程中,圆周被分成4个小段。每个小段中的点,对于原来的和即将选取的合并点或者均为顺时针较近,或者均为逆时针较近。
每次分别计算这四个段中的距离的改变值,然后更新分割四个段的临界下标即可。
最后,我的代妈长度是2333B,yeah~
#include <iostream>
#include <stdio.h>
using namespace std;
int pos[100000];
int gs = 0;
int mn(int a, int b){
return (a>b) ? b : a;
}
int cwDist(int i1, int i2){
if(i1 <= i2) return pos[i2]-pos[i1];
return pos[i2] + 10000000 - pos[i1];
}
int dist(int i1, int i2){
int cwd = cwDist(i1, i2);
if(cwd <= 5000000) return cwd;
return 10000000-cwd;
}
int geshu(int i1, int i2){
//i1到i2的前闭后开区间的数的个数
if(i1 <= i2) return i2-i1;
return i2+gs-i1;
}
void quickSort(int s[], int l, int r)
{
if (l< r)
{
int i = l, j = r, x = s[l];
while (i < j)
{
while(i < j && s[j]>= x)
j--;
if(i < j)
s[i++] = s[j];
while(i < j && s[i]< x)
i++;
if(i < j)
s[j--] = s[i];
}
s[i] = x;
quickSort(s, l, i - 1);
quickSort(s, i + 1, r);
}
}
int main() {
scanf("%d", &gs);
for(int i = 0; i < gs; i++){
int temp;
scanf("%d", &temp);
temp --;
pos[i] = temp;
}
quickSort(pos, 0, gs-1);
int zg = -1, xg = -1;
for(int i = 0; i < gs; i++){
int xyg = (i+1)%gs;
if(cwDist(i, xyg) >= 5000000){
zg = i;
xg = xyg;
break;
}
}
if(zg != -1){
//存在两个点,下标分别为zg和xg,顺时针相邻,且相距大于一半。此时它们一定是端点。
long long int res = 0;
for(int i = 0; i < gs/2; i++){
res += cwDist((xg+i)%gs, (zg+gs-i)%gs);
}
printf("%I64d\n", res);
return 0;
}
int idx = 0;
int cwIdx = 0;
long long int res = 0;
for(int i = 0; i < gs; i++){
int tempDis = cwDist(0, i);
if(tempDis < 5000000){
cwIdx ++;
res += tempDis;
}
else{
res += (10000000-tempDis);
}
}
long long int tempRes = res;
while(1){
int newIdx = idx;
while(pos[newIdx] == pos[idx]){
newIdx ++;
}
if(newIdx >= gs) break;
long long int L = pos[newIdx] - pos[idx];
//idx和newIdx把圆周分成4段
//第一段:
tempRes += ((long long int)(newIdx - idx)) * L;
//第三段:
int newCwIdx = cwIdx;
while(cwDist(newIdx, newCwIdx) < 5000000){
tempRes -= dist(idx, newCwIdx);
tempRes += dist(newIdx, newCwIdx);
newCwIdx = (newCwIdx + 1) % gs;
}
//第二段:
tempRes -= L * ((long long int)(geshu(newIdx, cwIdx)));
//第四段:
tempRes += L * ((long long int)(geshu(newCwIdx, idx)));
if(tempRes < res) res = tempRes;
idx = newIdx;
cwIdx = newCwIdx;
}
printf("%I64d\n", res);
return 0;
}
Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator