CF 464E The Classic Problem
补一补之前听课时候的题。
考虑使用dij算法求最短路,因为边权存不下,所以考虑用主席树维护二进制位,因为每一次都只会在一个位置进行修改,所以可以暴力进位,这样均摊复杂度是对的。
《算法导论》给了证明:对于一个有$k$位的二进制计数器,假设每一次都从第0位$+1$,那么我们发现执行$n$次加法之后,发现第零位会变$\left \lfloor \frac{n}{1} \right \rfloor$次,第一位会变$\left \lfloor \frac{n}{2} \right \rfloor$次...而第$n$位会变$\left \lfloor \frac{n}{2^n} \right \rfloor$次,这样子所有的操作次数就相当于$\sum_{i = 0}^{k - 1}\left \lfloor \frac{i}{2^i} \right \rfloor < n * \sum_{i = 0}^{\infty}\frac{1}{2^i} = 2n$,所以最坏情况下的时间为$O(n)$,每一次操作的均摊时间复杂度为$O(n) / n = O(1)$。
这样子只需要借助主席树写一个时间为$O(log)$的$cmp$函数就可以用堆优化dijkskra了,遇到进位就在线段树上暴力搞一搞,反正复杂度是对的。
数太大了直接用题目中给的$seed = 2, Mod = 1e9 + 7$的哈希哈希一下就好了。
时间复杂度$O(nlog^2n)$。
感觉就像是对着大佬的题解抄了一遍。
Code:
- #include <cstdio>
- #include <cstring>
- #include <queue>
- #include <cstdlib>
- using namespace std;
- const int N = 1e5 + ;
- const int P = 1e9 + ;
- int n, m, st, ed, lim = , bin[N << ];
- int tot = , head[N], pre[N];
- struct Edge {
- int to, nxt, val;
- } e[N << ];
- inline void add(int from, int to, int val) {
- e[++tot].to = to;
- e[tot].val = val;
- e[tot].nxt = head[from];
- head[from] = tot;
- }
- inline void read(int &X) {
- X = ; char ch = ; int op = ;
- for(; ch > ''|| ch < ''; ch = getchar())
- if(ch == '-') op = -;
- for(; ch >= '' && ch <= ''; ch = getchar())
- X = (X << ) + (X << ) + ch - ;
- X *= op;
- }
- inline void chkMax(int &x, int y) {
- if(y > x) x = y;
- }
- namespace PSegT {
- struct SegNode {
- int lc, rc, w;
- } s[N * ];
- int nodeCnt, root[N];
- #define mid ((l + r) >> 1)
- bool cmp(int x, int l, int r, int y) {
- if(l == r) return s[x].w > s[y].w;
- if(s[s[x].rc].w == s[s[y].rc].w) return cmp(s[x].lc, l, mid, s[y].lc);
- else return cmp(s[x].rc, mid + , r, s[y].rc);
- }
- bool modify(int &x, int l, int r, int pos, int y) {
- s[x = ++nodeCnt] = s[y];
- if(l == r) {
- s[x].w = s[y].w ^ ;
- return s[y].w;
- }
- int res;
- if(pos > mid) res = modify(s[x].rc, mid + , r, pos, s[y].rc);
- else {
- res = modify(s[x].lc, l, mid, pos, s[y].lc);
- if(res) res = modify(s[x].rc, mid + , r, mid + , s[y].rc);
- }
- s[x].w = (1LL * s[s[x].rc].w * bin[mid - l + ] % P + s[s[x].lc].w) % P;
- return res;
- }
- } using namespace PSegT;
- struct Node {
- int x, rt;
- bool operator < (const Node &oth) const {
- return cmp(rt, , lim, oth.rt);
- }
- };
- priority_queue <Node> Q;
- void dfs(int x, int dep) {
- if(x == st) {
- printf("%d\n%d ", dep, x);
- return;
- }
- dfs(pre[x], dep + );
- printf("%d ", x);
- }
- inline void out() {
- printf("%d\n", s[root[ed]].w);
- dfs(ed, );
- printf("\n");
- exit();
- }
- int main() {
- read(n), read(m);
- for(int x, y, v, i = ; i <= m; i++) {
- read(x), read(y), read(v);
- add(x, y, v), add(y, x, v);
- chkMax(lim, v);
- }
- lim += ;
- read(st), read(ed);
- for(int i = bin[] = ; i <= lim; i++)
- bin[i] = 1LL * bin[i - ] * % P;
- nodeCnt = ;
- Q.push((Node) {st, root[st]});
- for(; !Q.empty(); ) {
- Node now = Q.top(); Q.pop();
- if(now.rt != root[now.x]) continue;
- if(now.x == ed) out();
- for(int i = head[now.x]; i; i = e[i].nxt) {
- int y = e[i].to, v;
- modify(v, , lim, e[i].val, root[now.x]);
- if(!root[y] || cmp(root[y], , lim, v)) {
- root[y] = v;
- Q.push((Node) {y, root[y]});
- pre[y] = now.x;
- }
- }
- }
- puts("-1");
- return ;
- }
CF 464E The Classic Problem的更多相关文章
- [Codeforces 464E] The Classic Problem(可持久化线段树)
[Codeforces 464E] The Classic Problem(可持久化线段树) 题面 给出一个带权无向图,每条边的边权是\(2^{x_i}(x_i<10^5)\),求s到t的最短路 ...
- CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度
题意描述 有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\).求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模). 题解 思路很简单--用主 ...
- Codeforces 464E. The Classic Problem
题目大意 给定一张$n$个点, $m$条边的无向图,求$S$ 到$T$的最短路,其中边权都是$2^k$的形式$n,m,k<=10^5$,结果对$10^9+7$取模 题解 大佬好厉害 跑一边dij ...
- Codeforces 464E The Classic Problem (最短路 + 主席树 + hash)
题意及思路 这个题加深了我对主席树的理解,是个好题.每次更新某个点的距离时,是以之前对这个点的插入操作形成的线段树为基础,在O(logn)的时间中造出了一颗新的线段树,相比直接创建n颗线段树更省时间. ...
- Codeforces 464E The Classic Problem(主席树+最短路+哈希,神仙题)
题目链接 题意:给出一张 \(n\) 个点 \(m\) 条边的无向图,第 \(i\) 条边连接 \(u_i,v_i\),边权为 \(2^{w_i}\),求 \(s\) 到 \(t\) 的最短路. \( ...
- Codeforces 464E #265 (Div. 1) E. The Classic Problem 主席树+Hash
E. The Classic Problem http://codeforces.com/problemset/problem/464/E 题意:给你一张无向带权图,求S-T的最短路,并输出路径.边权 ...
- 把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend
//把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend //dp[i][j]:把第i个数转成第j小的数,最小花费 //此题与po ...
- cf 633B A trivial problem
Mr. Santa asks all the great programmers of the world to solve a trivial problem. He gives them an i ...
- 【dp/贪心】CF 780 (Div. 3), problem: (C) Get an Even String
Problem - C - Codeforces 难度: 1300 input 6 aabbdabdccc zyx aaababbb aabbcc oaoaaaoo bmefbmuyw output ...
随机推荐
- Arc083_F Collecting Balls
传送门 题目大意 给定$N$,在$(1,0),(2,0)......(N,0)$和$(0,1),(0,2)...(0,N)$上都有$1$个机器人,同时给定$2N$个坐标$(x,y),x,y\in[1, ...
- 【java规则引擎】简单规则的rete网络示意图
一个Fact通过Session添加到规则网络中,如何进行规则匹配的大致过程如下 (1)通过根结点对象从EntryPointNode的Map集合中找到相应的EntryPointNode对象 (2)Ent ...
- BZOJ4861 [Beijing2017]魔法咒语
题意 Chandra 是一个魔法天才.从一岁时接受火之教会洗礼之后, Chandra 就显示出对火元素无与伦比的亲和力,轻而易举地学会种种晦涩难解的法术.这也多亏 Chandra 有着常人难以企及的语 ...
- es5中foreach的用法
HTML代码: <p id="result"></p> JS代码: var eleResult = document.getElementById(&quo ...
- 如何隐藏掉Nginx的版本号
最近新学习了一个命令curl,里面有一个参数-I可以查看到网站使用的是哪种服务器,比如: zhangxiaoliudeMacBook-Pro-2:~ zhangxiaoliu$ curl -I htt ...
- 蘑菇街 IM 项目 TeamTalk
源码 https://github.com/mogujie/TeamTalk 试用 http://tt.mogu.io/
- GWT实现平滑移动图片效果
在一些网站的首页上,顶部总会存在一些平滑移动的图片,一般用来投放广告或者业务介绍.多个图片只在一个区域展示,仅通过一些方法来不停的移动这个区域的图片来达到展示多个图片的目的.如果是普通的网页,使用Jq ...
- 蓝桥杯 历届试题 PREV-3 带分数
历届试题 带分数 时间限制:1.0s 内存限制:256.0MB 问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714. 还可以表示为:100 = 82 + 3 ...
- Python内置函数:read()
文章转载于:http://blog.csdn.net/sxingming/article/details/51337768(博主:快递小哥) 1> >>> f=open(r&q ...
- MongoTemplate聚合操作
Aggregation简单来说,就是提供数据统计.分析.分类的方法,这与mapreduce有异曲同工之处,只不过mongodb做了更多的封装与优化,让数据操作更加便捷和易用.Aggregation操作 ...