【倍增】【set】[NOIP2012] codevs1199 开车旅行
2015-10-18 00:15
281 查看
题目点这里
这题的复杂度基本就在预处理找在每个点A、B分别要开去哪上面了 = =倍增其实很水……
用set维护高度。因为只能从前往后,所以从后往前插入,然后取其前两个和后两个用他们之间的距离排个序,距离最小的是B去的地方,第二小是A去的地方。
记A+B各开一次为一轮。然后令f[i][j]为从i出发,开了2^j轮去了哪。fa[i][j]、fb[i][j]分别表示从a、b出发走2^j轮后开的距离。
于是
f[i][j] = f[f[i][j -1]][j -
1];
fa[i][j] = fa[i][j -1] +
fa[f[i][j -1]][j -
1];
fb[i][j] = fb[i][j -1] +
fb[f[i][j -1]][j -
1];
然后询问和倍增LCA差不多 = = 注意考虑最后只有A能走……对于第一个问枚举起点即可。
另外vijos上的数据很厉害啊,估计得手写treap了2333
这题的复杂度基本就在预处理找在每个点A、B分别要开去哪上面了 = =倍增其实很水……
用set维护高度。因为只能从前往后,所以从后往前插入,然后取其前两个和后两个用他们之间的距离排个序,距离最小的是B去的地方,第二小是A去的地方。
记A+B各开一次为一轮。然后令f[i][j]为从i出发,开了2^j轮去了哪。fa[i][j]、fb[i][j]分别表示从a、b出发走2^j轮后开的距离。
于是
f[i][j] = f[f[i][j -1]][j -
1];
fa[i][j] = fa[i][j -1] +
fa[f[i][j -1]][j -
1];
fb[i][j] = fb[i][j -1] +
fb[f[i][j -1]][j -
1];
然后询问和倍增LCA差不多 = = 注意考虑最后只有A能走……对于第一个问枚举起点即可。
另外vijos上的数据很厉害啊,估计得手写treap了2333
#include <cstdio> #include <iostream> #include <set> #include <algorithm> using namespace std; int N, x0, M, S, x1; struct city { int pos, high; bool operator < (const city &b) const { return high < b.high; } }c[100005]; set <city> s; struct temp { int pos, dif; bool operator < (const temp &b) const { if (dif != b.dif) return dif < b.dif; return c[pos].high < c[b.pos].high; } }t[5]; int nexta[100005], nextb[100005], f[100005][20]; long long fa[100005][20], fb[100005][20]; inline void Find(int i) { set <city> :: iterator it = s.find(c[i]); int add = 0; if (it != s.begin()) { -- it; t[++ add] = (temp) { it -> pos, abs(it -> high - c[i].high) }; if (it != s.begin()) { -- it; t[++ add] = (temp) { it -> pos, abs(it -> high - c[i].high) }; ++ it; } ++ it; } if ((++ it) != s.end()) { t[++ add] = (temp) { it -> pos, abs(it -> high - c[i].high) }; if ((++ it) != s.end()) t[++ add] = (temp) { it -> pos, abs(it -> high - c[i].high) }; } sort(t + 1, t + add + 1); nextb[i] = t[1].pos; if (add == 1) return; nexta[i] = t[2].pos; } inline void Query(int St, int X, long long &ta, long long &tb) { for (int i = 19; ~i; -- i) if (f[St][i] && fa[St][i] + fb[St][i] <= X) { ta += fa[St][i]; tb += fb[St][i]; X -= fa[St][i] + fb[St][i]; St = f[St][i]; } int posa = nexta[St]; if (!posa) return; int dis = abs(c[posa].high - c[St].high); if (dis <= X) ta += dis; } int main() { ios :: sync_with_stdio(false); cin >> N; for (int i = 1; i <= N; ++ i) { cin >> c[i].high; c[i].pos = i; } for (int i = N; i; -- i) { s.insert(c[i]); if (i ^ N) Find(i); } for (int i = 1; i <= N; ++ i) { int pos1 = nexta[i], pos2 = nextb[nexta[i]]; fa[i][0] = pos1 ? abs(c[pos1].high - c[i].high) : 0; fb[i][0] = pos2 ? abs(c[pos2].high - c[pos1].high) : 0; f[i][0] = pos2; } for (int j = 1; j < 20; ++ j) { for (int i = 1; i <= N; ++ i) { f[i][j] = f[f[i][j - 1]][j - 1]; fa[i][j] = fa[i][j - 1] + fa[f[i][j - 1]][j - 1]; fb[i][j] = fb[i][j - 1] + fb[f[i][j - 1]][j - 1]; } } cin >> x0; int ans = 0; long long ansa = 1e15, ansb = 0ll; for (int i = 1; i <= N; ++ i) { long long ta = 0ll, tb = 0ll; Query(i, x0, ta, tb); if (tb && (!ans || ansa * tb > ansb * ta)) { ansa = ta; ansb = tb; ans = i; } } cout << ans << endl; for (cin >> M; M --; ) { cin >> S >> x1; long long ta = 0ll, tb = 0ll; Query(S, x1, ta, tb); cout << ta << " " << tb << endl; } return 0; }
相关文章推荐
- 物理引擎UIDynamic
- 呈现样式UIModalPresentation
- service broker发送的消息不可达
- Android WiFi密码(查看工具)
- 牛顿插值多项式
- iOS之代码规范
- Python学习
- 多线程 GCD
- 套接字Socket
- php 魔法函数 __autoload()
- ios文件,图片上传服务器
- FMDB数据库框架
- 连接oracle数据库报ora-01019
- poj 2409 Let it Bead Polya波利亚定理
- int ,long , long long, __int64等类型的范围
- 数据库-Core Data
- SQLite编码
- Python 配置日志
- PHPStorm与查找相关的快捷键
- 多线程 NSThread