第四题5比较大小的方法题以及步骤

【问题描述】
  C国共有$n$个城市。有$n-1$条双向道路,每条道路连接两个城市,任意两个城市之间能互相到达。小R来到C国旅行,他共规划了$m$条旅行的路线, 第$i$条旅行路线的起点是$s_i$,终点是$t_i$。在旅行过程中,小R每行走一单位长度的路需要吃一单位的食物。C国的食物只能在各个城市中买到,而且不同城市的食物价格可能不同。  然而,小R不希望在旅行中为了购买较低价的粮食而绕远路,因此他总会选择最近的路走。现在,请你计算小R规划的每条旅行路线的最小花费是多少。
【输入格式】
  第一行包含2个整数$n$和$m$。  第二行包含$n$个整数。第$i$个整数$w_i$表示城市$i$的食物价格。  接下来$n-1$行,每行包括3个整数$u, v, e$,表示城市$u$和城市$v$之间有一条长为$e$的双向道路。  接下来$m$行,每行包含2个整数$s_i$和$t_i$,分别表示一条旅行路线的起点和终点。
【输出格式】
  输出$m$行,分别代表每一条旅行方案的最小花费。
【样例输入】
6 41 7 3 2 5 61 2 41 3 52 4 13 5 23 6 12 54 66 45 6
【样例输出】
【样例说明】
对于第一条路线,小R会经过2-&1-&3-&5。其中在城市2处以7的价格购买4单位粮食,到城市1时全部吃完,并用1
的价格购买7单位粮食,然后到达终点。
【评测用例规模与约定】
  前10%的评测用例满足:$n, m & 20, w_i & 20$;  前30%的评测用例满足:$n, m & 200$;  另有40%的评测用例满足:一个城市至多与其它两个城市相连。  所有评测用例都满足:$1 & n, m & 10^5,1 & w_i & 10^6,1 & e & 10000$。
首先注意到,一条路径的选择方案,一定是从一个点走到下一个比它便宜的点,这之间的食物都在这个点购买。
而这个信息不具有可加性,却具有可减性。
之前在网上搜到了一篇自称要维护两遍单调栈三个lct的博客,但是维护单调栈的最坏时间复杂度为$O(n^2)$,故无法通过所有的测试数据。
下面介绍一种基于点分治的做法。
假设当前分治中心为T,对于一个询问u-&v,可以被拆成u-&T,T-&v,对于u-&T的费用,我们可以在倍增数组上二分出u上面第一个比它便宜的位置,用这个位置的信息可以直接得出u的信息。
现在考虑T-&v的费用,对于每一个询问,都附加了一个状态,表示之前便宜的费用c,我们需要在T-&v的路径上找到第一个比它便宜的点设为x(这个可以通过dfs时维护一个前缀最小值数据来二分求得),这一段用的费用是dis(T, x) * c,剩下的部分就是从x向下走走到v的费用,我们可以通过dfs求出每个点到T的费用,之前已经提到过,维护的信息具有可减性,就可以$O(1)$的时间算出从一个点往下走的走到某个点的费用。
至此,问题在$O(n\log^2n)$的时间复杂度,$O(n\log n)$的空间复杂度内解决。
【代码】(滥用stl导致常数非常大)
1 #include&bits/stdc++.h&
3 using namespace
5 typedef long long LL;
6 typedef pair&int, int&
7 #define FI first
8 #define SE second
9 #define for_edge(u, it) for(vector&pii&::iterator it = G[u].begin(); it != G[u].end(); ++it)
11 const int N = 100000 + 10;
13 vector&pii& G[N];
14 vector&int& Q[N], q1[N], q2[N];
15 LL dis[N], disv[N];
16 int cost[N], sz[N], maxsz[N], top[N],
17 pii q_info[N];
18 pair&LL, int& ans[N];
19 bool centre[N];
21 #define v it-&FI
22 void get_size(int u, int fa) {
maxsz[u] = 0, sz[u] = 1;
for_edge(u, it) if(v != fa && !centre[v]) {
get_size(v, u);
sz[u] += sz[v];
maxsz[u] = max(maxsz[u], sz[v]);
31 void get_root(int u, int fa, int r) {
maxsz[u] = max(maxsz[u], sz[r] - sz[u]);
if(maxsz[u] & maxsz[root]) root =
for_edge(u, it) if(v != fa && !centre[v]) {
get_root(v, u, r);
39 int anc[17][N], val[17][N];
41 int tot_
43 void get_top(int u, int fa, int pre) {
anc[0][u] = fa, val[0][u] = cost[u];
int tmp = clock();
for(int i = 1; i & 17; i++) {
val[i][u] = min(val[i-1][u], val[i-1][anc[i-1][u]]);
anc[i][u] = anc[i-1][anc[i-1][u]];
tot_time += clock() -
for_edge(u, it) if(v != fa && !centre[v]) {
dis[v] = dis[u] + it-&SE, get_top(v, u, pre);
58 int pre[N];
60 int find(int u) {
int cost_u = cost[u];
//int tmp = clock();
for(int i = 16; i &= 0; i--) {
if(val[i][u] &= cost_u) u = anc[i][u];
//tot_time += clock() -
70 void calc_1(int u, int fa) {
int anc = find(u);
if(anc) pre[u] = pre[anc];
else anc = root, pre[u] = // be root when not exist
disv[u] = (dis[u] - dis[anc]) * cost[u] + disv[anc];
for(unsigned i = 0; i & q1[u].size(); i++) {
ans[q1[u][i]] = make_pair(disv[u], cost[pre[u]]);
for_edge(u, it) if(v != fa && !centre[v]) {
calc_1(v, u);
87 void calc_2(int u, int fa, int fee) {
static int val[N], id[N],
disv[u] = (dis[u] - dis[fa]) * fee + disv[fa];
id[tot] = u, val[tot] = cost[u];
if(tot++) val[tot-1] = min(val[tot-2], cost[u]);
id[tot] = // be u when not exist
for(unsigned i = 0; i & q2[u].size(); i++) {
int c = q2[u][i];
int anc = id[lower_bound(val, val + tot, ans[c].SE, greater&int&()) - val];
ans[c].FI += ans[c].SE * (dis[anc] - dis[root]) + disv[u] - disv[anc];
for_edge(u, it) if(v != fa && !centre[v]) {
calc_2(v, u, min(fee, cost[u]));
106 void solve(int u) {
if(!Q[u].size()) return;
get_size(u, 0);
root = u, get_root(u, 0, u);
//cerr && sz[u] && ' ' && maxsz[root] &&
vector&int& vec_q;
vec_q.swap(Q[u]);
centre[u = root] = 1, top[u] = u, dis[u] = 0;
for(int i = 0; i & 17; i++) anc[i][u] = val[i][u] = 0;
val[0][u] = cost[u];
for_edge(u, it) if(!centre[v]) {
dis[v] = it-&SE, get_top(v, u, v);
for(unsigned i = 0; i & vec_q.size(); i++) {
int c = vec_q[i], x = q_info[c].FI, y = q_info[c].SE;
if(top[x] == top[y]) Q[top[x]].push_back(c);
else q1[x].push_back(c), q2[y].push_back(c);
disv[u] = 0, pre[u] =
calc_1(u, 0);
disv[u] = 0;
calc_2(root, 0, cost[u]);
for(unsigned i = 0; i & vec_q.size(); i++) {
int c = vec_q[i], x = q_info[c].FI, y = q_info[c].SE;
q1[x].clear(), q2[y].clear();
for_edge(u, it) if(!centre[v]) {
145 #undef v
147 int main() {
148 #ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
int start_time = clock();
152 #endif
int n, scanf("%d%d", &n, &m);
for(int i = 1; i &= i++) {
scanf("%d", cost + i);
for(int i = 1; i & i++) {
scanf("%d%d%d", &u, &v, &w);
G[u].push_back(pii(v, w));
G[v].push_back(pii(u, w));
for(int i = 0; i & i++) {
pii &cur = q_info[i];
scanf("%d%d", &cur.FI, &cur.SE);
if(cur.FI != cur.SE) Q[1].push_back(i);
for(int i = 0; i & i++) {
printf("%I64d\n", ans[i].FI);
176 #ifdef DEBUG
fprintf(stderr, "time used : %.5fs, %.5fs\n", (double) (clock() - start_time) / CLOCKS_PER_SEC, (double)tot_time / CLOCKS_PER_SEC);
178 #endif
阅读(...) 评论()第五版物理化学第四章习题答案_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
第五版物理化学第四章习题答案
阅读已结束,下载文档到电脑
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩18页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢初三化学第四、五单元测试题及答案_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
初三化学第四、五单元测试题及答案
&&初三化学上册第四、第五单元测试题及答案
阅读已结束,下载文档到电脑
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩5页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢}

我要回帖

更多关于 比较大小的方法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信