【倍增】【set】[NOIP2012] codevs1199 开车旅行
来源:互联网 发布:网页编程课程设计 编辑:程序博客网 时间:2024/05/01 22:25
题目点这里
这题的复杂度基本就在预处理找在每个点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;}
2 0
- 【倍增】【set】[NOIP2012] codevs1199 开车旅行
- noip2012 开车旅行 set+倍增
- NOIP2012 开车旅行:SET+倍增
- codevs1199开车旅行[倍增] 留坑
- NOIP2012 T3开车旅行 set+倍增
- NOIP2012 开车旅行 (倍增)
- NOIP2012 开车旅行 【倍增】
- 【vijos1780】【NOIP2012】开车旅行 倍增
- NOIP2012 开车旅行 (倍增)
- 洛谷1081/codevs1199 开车旅行 链表,倍增,模拟
- noip2012 开车旅行 (倍增处理)
- NOIP2012 开车旅行 [Splay] [ST倍增]
- 【NOIP 2012】开车旅行 倍增+set
- 【NOIP2012】开车旅行
- NOIP2012 开车旅行
- NOIP2012 D1T3 开车旅行
- 【NOIP2012】Day1T3 开车旅行
- NOIP2012 开车旅行
- Q版对战俏皮《宝贝坦克》新服火辣开启
- Gitlab升级
- Eclipse初始化设置
- Hadoop排序工具用法小结
- github学习
- 【倍增】【set】[NOIP2012] codevs1199 开车旅行
- vim终极配置:spf13-vim
- css网页编程【详解】
- org.springframework.core.io.InputStreamSource接口源码分析
- 1.Untiy3D学习(事件分发器)
- Java的native关键字
- Threat Intelligence-Driven Risk Analysis
- SQLServer 2014 内存优化表
- int ,long , long long, __int64等类型的范围