题意描述

有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\)。求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模)。

题解

思路很简单——用主席树维护每个点的\(dis\)。因为每次更新某个点\(v\)的\(dis_v\)的时候,新的\(dis_v\)都是某个点\(u\)的\(dis_u + 2^{w_{u, v}}\),相当于在原先\(u\)对应的主席树基础上修改,得到新的一棵主席树,作为\(v\)对应的主席树。

主席树(线段树)维护二进制高精度怎么维护呢?像松松松那么维护就好了 = =

需(wǒ)要(fàn)注(guò)意的问题:

  1. 如果你用priority_queue来做Dijkstra,又中途修改了节点对应的dis,会影响堆的性质,会WA。正确做法是在priority_queuepair<节点编号,当前dis>
  2. 主席树的空间要适当优化优化?例如查询操作的时候,pushdown会创造新的节点,但是以后就不会用到这群节点了,于是一次完整的查询操作之后把这些新节点都删掉就好了,空间可以得到明显优化。

代码

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#define space putchar(' ')
#define enter putchar('\n')
typedef long long ll;
using namespace std;
template <class T>
void read(T &x){char c;bool op = 0;while(c = getchar(), c < '0' || c > '9')if(c == '-') op = 1;x = c - '0';while(c = getchar(), c >= '0' && c <= '9')x = x * 10 + c - '0';if(op) x = -x;
}
template <class T>
void write(T x){if(x < 0) putchar('-'), x = -x;if(x >= 10) write(x / 10);putchar('0' + x % 10);
}const int N = 100100, M = 40000007, mod = 1000000007, P = 1000000021;
int n, s, t, maxn = 100098, m, hsh100[N], hsh111[N], ans100[N], ans111[N];
int ecnt, adj[N], nxt[2*N], go[2*N], w[2*N], pre[N], stk[N], top;
int ls[M], rs[M], hsh[M], ans[M], tot, root[N];
bool lazy[M], vis[N];
void adde(int u, int v, int ww){go[++ecnt] = v;nxt[ecnt] = adj[u];adj[u] = ecnt;w[ecnt] = ww;
}
int newnode(int old){int k = ++tot;ls[k] = ls[old], rs[k] = rs[old];hsh[k] = hsh[old], ans[k] = ans[old], lazy[k] = lazy[old];return k;
}
int pushdown(int k){if(!lazy[k]) return newnode(k);k = newnode(k);lazy[k] = 0;ls[k] = newnode(ls[k]), rs[k] = newnode(rs[k]);lazy[ls[k]] = lazy[rs[k]] = 1;hsh[ls[k]] = hsh[rs[k]] = ans[ls[k]] = ans[rs[k]] = 0;return k;
}
int change0(int k, int l, int r, int ql, int qr){if(ql <= l && qr >= r) return k = newnode(k), lazy[k] = 1, hsh[k] = ans[k] = 0, k;k = pushdown(k);int mid = (l + r) >> 1;if(ql <= mid) ls[k] = change0(ls[k], l, mid, ql, qr);if(qr > mid) rs[k] = change0(rs[k], mid + 1, r, ql, qr);hsh[k] = (hsh[ls[k]] + (ll)hsh[rs[k]] * hsh100[mid - l + 1]) % P;ans[k] = (ans[ls[k]] + (ll)ans[rs[k]] * ans100[mid - l + 1]) % mod;return k;
}
int change1(int k, int l, int r, int p){if(l == r) return k = newnode(k), lazy[k] = 0, hsh[k] = ans[k] = 1, k;k = pushdown(k);int mid = (l + r) >> 1;if(p <= mid) ls[k] = change1(ls[k], l, mid, p);else rs[k] = change1(rs[k], mid + 1, r, p);hsh[k] = (hsh[ls[k]] + (ll)hsh[rs[k]] * hsh100[mid - l + 1]) % P;ans[k] = (ans[ls[k]] + (ll)ans[rs[k]] * ans100[mid - l + 1]) % mod;return k;
}
int find0(int k, int l, int r, int ql, int qr){if(hsh[k] == hsh111[r - l + 1] && ans[k] == ans111[r - l + 1]) return -1;if(l == r) return l;k = pushdown(k);int mid = (l + r) >> 1;if(ql > mid) return find0(rs[k], mid + 1, r, ql, qr);int ret = find0(ls[k], l, mid, ql, qr);if(ret != -1) return ret;return find0(rs[k], mid + 1, r, ql, qr);
}
int add(int k, int p){int mem_tot = tot;int q = find0(k, 0, maxn, p, maxn);tot = mem_tot;k = change1(k, 0, maxn, q);if(p < q) k = change0(k, 0, maxn, p, q - 1);return k;
}
bool diff(int k1, int k2, int l, int r){if(l == r) return hsh[k1] < hsh[k2];k1 = pushdown(k1), k2 = pushdown(k2);int mid = (l + r) >> 1;if(hsh[rs[k1]] == hsh[rs[k2]] && ans[rs[k1]] == ans[rs[k2]])return diff(ls[k1], ls[k2], l, mid);else return diff(rs[k1], rs[k2], mid + 1, r);
}
struct Data {int node, root;bool operator < (const Data &b) const {int mem_tot = tot;bool ret = diff(b.root, root, 0, maxn);tot = mem_tot;return ret;}
};
priority_queue <Data> que;int main(){read(n), read(m);hsh100[0] = ans100[0] = 1;for(int i = 1; i <= maxn + 1; i++){hsh100[i] = hsh100[i - 1] * 2 % P;ans100[i] = ans100[i - 1] * 2 % mod;hsh111[i] = (hsh100[i] - 1 + P) % P;ans111[i] = (ans100[i] - 1 + mod) % mod;}for(int i = 1, u, v, ww; i <= m; i++)read(u), read(v), read(ww), adde(u, v, ww), adde(v, u, ww);read(s), read(t);root[0] = add(0, maxn - 1);for(int i = 1; i <= n; i++)if(i != s) root[i] = root[0];que.push((Data){s, root[s]});while(!que.empty()){int u = que.top().node;que.pop();if(vis[u]) continue;vis[u] = 1;for(int e = adj[u], v; e; e = nxt[e]){v = go[e];int tmp = add(root[u], w[e]);if(diff(tmp, root[v], 0, maxn))root[v] = tmp, pre[v] = u, que.push((Data){v, root[v]});}}if(ans[root[t]] == ans100[maxn - 1] && hsh[root[t]] == hsh100[maxn - 1])return puts("-1"), 0;write(ans[root[t]]), enter;stk[++top] = t;while(pre[stk[top]]) stk[top + 1] = pre[stk[top]], top++;write(top), enter;while(top) write(stk[top--]), top ? space : enter;return 0;
}

转载于:https://www.cnblogs.com/RabbitHu/p/CF464E.html

CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度相关推荐

  1. CF464E-The Classic Problem【最短路,主席树】

    正题 题目链接:https://www.luogu.com.cn/problem/CF464E 题目大意 nnn个点mmm条边的一张无向图,第iii条边长度为2xi2^{x_i}2xi​,求sss到t ...

  2. CodeForces - 1422F Boring Queries(主席树+线段树/RMQ)

    题目链接:点击查看 题目大意:给出 n 个数组成的数组 a ,再给出 m 次询问,每次询问需要回答区间 [ l , r ] 中所有元素的最小公倍数,强制在线 题目分析:首先考虑多个数的最小公倍数该如何 ...

  3. Codeforces Round #675 (Div. 2) F. Boring Queries 区间lcm + 主席树

    传送门 文章目录 题意: 思路: 题意: 给你一个长度为nnn的序列aaa,qqq个询问,每次询问[l,r][l,r][l,r]内的lcmlcmlcm是多少,对1e9+71e9+71e9+7取模. n ...

  4. 线段树/扫描线问卷调查反馈——Rmq Problem / mex(主席树),Boring Queries(二分+st表+主席树),Colorful Squares(扫描线)

    文章目录 Rmq Problem / mex Boring Queries Colorful Squares Rmq Problem / mex luogu4137 对aia_iai​建权值线段树 再 ...

  5. CF464E The Classic Problem(主席树+哈希+最短路)

    CF464E The Classic Problem problem solution code problem 题目链接 solution 经典题. 本题很特别的是每条边的边权都是 222 的幂,而 ...

  6. Codeforces 776D The Door Problem

    题目链接:http://codeforces.com/contest/776/problem/D 把每一个钥匙拆成两个点${x,x+m}$,分别表示选不选这把钥匙. 我们知道一扇门一定对应了两把钥匙. ...

  7. codeforces C. Sonya and Problem Wihtout a Legend(dp or 思维)

    题目链接:http://codeforces.com/contest/713/problem/C 题解:这题也算是挺经典的题目了,这里附上3种解法优化程度层层递进,还有这里a[i]-i<=a[i ...

  8. Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake 线段树维护dp

    D. Babaei and Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/D Description As you ...

  9. Codeforces Round #740 (Div. 2) F. Top-Notch Insertions 线段树 / 平衡树 + 组合数学

    传送门 文章目录 题意: 思路: 题意: 思路: 考虑最终的序列是什么鸭子的,首先序列肯定单调不降,也就是a1≤a2≤a3≤...≤ana_1\le a_2\le a_3\le ...\le a_na ...

最新文章

  1. DSSM(DEEP STRUCTURED SEMANTIC MODELS)
  2. 奶粉运营,跑数据三个模板。
  3. php认识正则吗,php正则表达式有什么用
  4. RNN、LSTM、GRU的原理和实现
  5. Mac OS X:解决开机总是显示“电脑关机是因为发生了问题”
  6. vmware vSAN 入门
  7. python贪心算法几个经典例子_贪心算法及示例,Python
  8. 关于killer网卡在linux 2.6.11版本以上的驱动安装
  9. 基于hadoop的商品推荐引擎
  10. 建设银行网银U盾证书更新教程【证书更新】
  11. Treeview 无限分类非递归终极解决方案VB
  12. 小卖部做成了我们没有做成的事
  13. 能去百度、滴滴、阿里的算法工程师到底有多牛?听说个个都是人才,说话又好听...
  14. Python科研数据分析专题之正态性检验
  15. JS将秒数换算成时分秒 以及转化为年月日 时分秒以及多长时间以前
  16. 剑客vs刀客 Java vs .NET
  17. vue v-html 中@click 和 class 不生效问题解决方案
  18. Eclipse 的常用快捷键
  19. 如何将Excel数据快速生成炫酷仪表盘
  20. mysql tdsql_TDSQL

热门文章

  1. 身份证号码有效性验证
  2. 多元线性回归之预测房价
  3. 各类牛B电影,暑假慢慢看完
  4. 2022年软件测试行业就业发展前景,软件测试前景好吗?我该学什么?
  5. NBA球星库里入股FTX并担任品牌大使,后者此前已签下布雷迪
  6. SQL Server将主键索引,改为非聚集索引
  7. 计算机硬件加速怎么开,怎么开启显卡硬件加速?开启显卡硬件的加速功能步骤...
  8. xy坐标正负方向_道路施工图纸上x坐标和y坐标分别代表什么方向?哪个代表南北方向?哪个代表东西方向?...
  9. Linux内核在中国大发展的黄金十年-写于中国Linux存储、内存管理和文件系统峰会十周年之际...
  10. 项目编译不成功原因之一的引用jar包问题