[NOIP2012] 开车旅行
题目描述
输入格式
输出格式
样例
数据范围与提示
我被这道题调试了整整两天。
原来wa的原因是一个<= 写成 >= 。
还有我的读入优化一直用的只有正数...
判了负数就A了。
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <set> #include <map> using namespace std; #define int long long inline int read() { int res=0;char ch=getchar();bool flag=0; while(!isdigit(ch)) {if(ch=='-')flag=1;ch=getchar();} while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return flag ? -res : res; } #define N 100005 #define reg register int n, h[N], Si, X0; int ga[N], gb[N]; struct date { int id, h; friend bool operator < (date a, date b) { return a.h < b.h; } }; int f[20][N][2];//走2^i天,从j城市出发,由a/b先走最后在哪座城市 int da[20][N][2], db[20][N][2]; inline void Calc(int S, int x, int &la, int &lb) { int p = S; for (reg int i = Si ; i >= 0 ; i --) { if (f[i][p][0] and la + lb + da[i][p][0] + db[i][p][0] <= x) la += da[i][p][0], lb += db[i][p][0], p = f[i][p][0]; } } multiset <date> se; inline int abss(int x) {return x < 0 ? -x : x;} signed main() { n = read(); Si = 18; for (reg int i = 1 ; i <= n; i ++) scanf("%lld", &h[i]); h[0] = 2e9, h[n+1] = -2e9; date init1, init2; init1.id = 0, init1.h = 2e9; init2.id = n + 1, init2.h = -2e9; se.insert(init1); se.insert(init1); se.insert(init2); se.insert(init2); for (reg int i = n ; i >= 1 ; i --) { date e; e.h = h[i], e.id = i; se.insert(e); multiset<date> :: iterator it = se.lower_bound(e); int pre, nxt, preh, nxth; it++; nxt = (*it).id, nxth = (*it).h; it--, it--; pre = (*it).id, preh = (*it).h; it++; if (abss(nxth - h[i]) >= abss(preh - h[i])) { gb[i] = pre; it--, it--; if (abss(nxth - h[i]) >= abss((*it).h - h[i])) ga[i] = (*it).id; else ga[i] = nxt; } else { gb[i] = nxt; it++, it++; if (abss(preh - h[i]) > abss((*it).h - h[i])) ga[i] = (*it).id; else ga[i] = pre; } } // for (reg int i = n ; i >= 1 ; i --) // printf("%lld %lld %lld\n", i, ga[i], gb[i]); for (reg int i = 1 ; i <= n ; i ++) f[0][i][0] = ga[i], f[0][i][1] = gb[i]; for (reg int j = 1 ; j <= n ; j ++) for (reg int k = 0 ; k <= 1 ; k ++) f[1][j][k] = f[0][f[0][j][k]][1-k]; for (reg int i = 2 ; i <= Si ; i ++) for (reg int j = 1 ; j <= n ; j ++) for (reg int k = 0 ; k <= 1 ; k ++) f[i][j][k] = f[i-1][f[i-1][j][k]][k]; for (reg int i = 1 ; i <= n ; i ++) da[0][i][1] = 0, da[0][i][0] = abs(h[ga[i]] - h[i]); for (reg int j = 1 ; j <= n ; j ++) da[1][j][1] = abs(h[f[1][j][1]] - h[f[0][j][1]]), da[1][j][0] = da[0][j][0]; for (reg int i = 2 ; i <= Si ; i ++) for (reg int j = 1 ; j <= n ; j ++) for (reg int k = 0 ; k <= 1 ; k ++) da[i][j][k] = da[i-1][j][k] + da[i-1][f[i-1][j][k]][k]; for (reg int i = 1 ; i <= n ; i ++) db[0][i][0] = 0, db[0][i][1] = abs(h[gb[i]] - h[i]); for (reg int j = 1 ; j <= n ; j ++) db[1][j][1] = db[0][j][1], db[1][j][0] = abs(h[f[1][j][0]] - h[f[0][j][0]]); for (reg int i = 2 ; i <= Si ; i ++) for (reg int j = 1 ; j <= n ; j ++) for (reg int k = 0 ; k <= 1 ; k ++) db[i][j][k] = db[i-1][j][k] + db[i-1][f[i-1][j][k]][k]; X0 = read(); double nres = 2e15 * 1.0; int ans1 = 0; for (reg int i = 1 ; i <= n ; i ++) { int la = 0, lb = 0; Calc(i, X0, la, lb); if (!lb) { if (nres > 2e15*1.0) nres = 2e15*1.0, ans1 = i; else if (nres == 2e15*1.0 and h[ans1] < h[i]) ans1 = i; continue; } else { if (((double)la / (double)lb) < nres) nres = ((double)la/(double)lb), ans1 = i; else if (((double)la / (double)lb) == nres and h[i] > h[ans1]) ans1 = i; } } printf("%lld\n", ans1); int q = read(); while(q--) { int S = read(), x = read(); int la = 0, lb = 0; Calc(S, x, la, lb); printf("%lld %lld\n", la, lb); } return 0; }