E. The Classic Problem

http://codeforces.com/problemset/problem/464/E

题意:给你一张无向带权图,求S-T的最短路,并输出路径。边权为2^xi。xi≤105,n≤105,m≤105.

想法:边权太大了,可以用数组按二进制存下来。带高精度跑太费事了。

观察一下,这里距离的更新:c=(a,b),用dis[a]更新dis[b]

①dis[b][c]=0,直接赋为1.只有一个数字改变。

②dis[b][c]=1,需要进位。考虑极端情况数据,xi都是一个数,那么需要进位O(m/2+m/4+m/8+...+1)≈O(m)

所以总改变次数为O(m),使用主席树维护这个二进制数组。

然后比较大小,可以在主席树上二分,如果左儿子一样就往右儿子走,反之走左儿子。判断是否一样可以用Hash。一次比较为O(logm).

于是dijkstra+heap+主席树:

空间复杂度O(mlogm).

时间复杂度O(mlog^2m).

ps:因为有进位要给主席树预留logm个空间。

 #include<cstdio>
#include<algorithm>
const int len(),lem(),HP(),MP(),RP();
struct ChairManTree{int nx[],sum;}tree[lem+];
int stot,root[len+];int H[len+],b[len+],tp;
struct Node{int nd,nx,co;}bot[len*+];
int tot,first[len+];
int n,m,v[len+],u[len+],x[len+],axle[len+],up,big,s,t,last[len+];
void add(int a,int b,int c){bot[++tot]=(Node){b,first[a],c};first[a]=tot;}
int two(int x)
{
int l=,r=up,ans=,mid;
while(l<=r)
if(axle[mid=(l+r)>>]>=x){ans=mid;l=mid+;}else r=mid-;
return ans;
}
void update(int k,int l,int r)
{
tree[k].sum=(1ll*tree[tree[k].nx[]].sum*H[(r-l+)>>]+tree[tree[k].nx[]].sum)%MP;
}
void build(int k,int l,int r,int x)
{
if(l==r){tree[k].sum=x;return;}
int mid=(l+r)>>;
tree[k].nx[]=++stot;build(stot,l,mid,x);
tree[k].nx[]=++stot;build(stot,mid+,r,x);
update(k,l,r);
}
int cmp(int k1,int k2)//-:k1<k2,+:k2>k1,0:k1=k2,return +-pos
{
int l=,r=up+,mid;
while(l!=r)
{
mid=(l+r)>>;
if(tree[tree[k1].nx[]].sum==tree[tree[k2].nx[]].sum)
k1=tree[k1].nx[],k2=tree[k2].nx[],l=mid+;
else k1=tree[k1].nx[],k2=tree[k2].nx[],r=mid;
}
if(tree[k1].sum==tree[k2].sum)return ;
if(tree[k1].sum<tree[k2].sum)return -l;
return l;
}
int insert(int k,int l,int r,int &x)
{
int z=++stot;
if(l==r)
{
if(tree[k].sum)tree[z].sum=,x--;//进位
else tree[z].sum=;return z;
}
int mid=(l+r)>>,tmp;tree[z]=tree[k];
if(x>mid){tmp=insert(tree[k].nx[],mid+,r,x);tree[z].nx[]=tmp;}
if(x<=mid){tmp=insert(tree[k].nx[],l,mid,x);tree[z].nx[]=tmp;}
update(z,l,r);
return z;
}
void dfs(int x,int l,int r)
{
if(l==r){b[l]=tree[x].sum;return;}
int mid=(l+r)>>;
dfs(tree[x].nx[],l,mid);
dfs(tree[x].nx[],mid+,r);
}
struct data
{
int x,y;
bool operator <(const data &A)const//默认小根堆
{
return (cmp(x,A.x)>);
}
}q[len*+];int qfree;
void Dijkstra()
{
for(int i=;i<=n;i++)root[i]=root[n+];
root[s]=root[];q[qfree=]=(data){root[s],s};
while(qfree)
{
data now=q[];std::pop_heap(q+,q++qfree);qfree--;
while(root[now.y]!=now.x&&qfree){now=q[];std::pop_heap(q+,q++qfree);qfree--;}
if(root[now.y]!=now.x&&!qfree)break;
for(int v=first[now.y];v;v=bot[v].nx)
{
int tmp=insert(root[now.y],,up+,bot[v].co);
int pos=cmp(tmp,root[bot[v].nd]);
if (pos>=)continue;
last[bot[v].nd]=now.y;
root[bot[v].nd]=tmp;
q[++qfree]=(data){root[bot[v].nd],bot[v].nd};
std::push_heap(q+,q++qfree);
}
}
}
void put()
{
if(root[t]==root[n+])printf("-1");
else
{
if(tree[root[t]].sum==tree[root[]].sum)printf("0\n");
else
{
dfs(root[t],,up+);
int tmp=,j=,l=;
for(int i=up;i>=;i--)
{
while(l<axle[i]){l++;j=(j+j)%RP;}
tmp=(tmp+1ll*j*b[i])%RP;
}
printf("%d\n",tmp);
}
int now=t;b[tp=]=t;
while(last[now])
{
now=last[now];
b[++tp]=now;
}
printf("%d\n",tp);
for(int i=tp;i>=;i--)
printf("%d ",b[i]);
}
}
bool cmp2(int a,int b){return a>b;}
int main()
{
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",v+i,u+i,x+i);
if(x[i]>big)big=x[i];
}
scanf("%d%d",&s,&t);
for(int i=;i<=big+;i++)axle[i]=big+-i;up=big+;
H[]=;for(int i=;i<=up+;i++)H[i]=(1ll*H[i-]*HP)%MP;
for(int i=;i<=m;i++)
{
x[i]=two(x[i]);
add(v[i],u[i],x[i]);
add(u[i],v[i],x[i]);
}
root[]=++stot;build(root[],,up+,);//zero
root[n+]=++stot;build(root[n+],,up+,);//INF
Dijkstra();
put();
return ;
}

Codeforces 464E #265 (Div. 1) E. The Classic Problem 主席树+Hash的更多相关文章

  1. Codeforces Round #321 (Div. 2) E. Kefa and Watch 线段树hash

    E. Kefa and Watch Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/580/prob ...

  2. Codeforces Round #265 (Div. 1) C. Substitutes in Number dp

    题目链接: http://codeforces.com/contest/464/problem/C J. Substitutes in Number time limit per test 1 sec ...

  3. Codeforces Round #265 (Div. 2) C. No to Palindromes! 构建无回文串子

    http://codeforces.com/contest/465/problem/C 给定n和m,以及一个字符串s,s不存在长度大于2的回文子串,如今要求输出一个字典比s大的字符串,且串中字母在一定 ...

  4. Codeforces Round #265 (Div. 2) E. Substitutes in Number

    http://codeforces.com/contest/465/problem/E 给定一个字符串,以及n个变换操作,将一个数字变成一个字符串,可能为空串,然后最后将字符串当成一个数,取模1e9+ ...

  5. Codeforces Round #265 (Div. 2) D. Restore Cube 立方体判断

    http://codeforces.com/contest/465/problem/D 给定8个点坐标,对于每个点来说,可以随意交换x,y,z坐标的数值.问说8个点是否可以组成立方体. 暴力枚举即可, ...

  6. Codeforces Round #265 (Div. 2) C. No to Palindromes! 构造不含回文子串的串

    http://codeforces.com/contest/465/problem/C 给定n和m,以及一个字符串s,s不存在长度大于2的回文子串,现在要求输出一个字典比s大的字符串,且串中字母在一定 ...

  7. Codeforces Round #265 (Div. 2) D. Restore Cube 立方体推断

    http://codeforces.com/contest/465/problem/D 给定8个点坐标.对于每一个点来说,能够任意交换x.y,z坐标的数值. 问说8个点能否够组成立方体. 暴力枚举就可 ...

  8. Codeforces Round #265 (Div. 2)

    http://codeforces.com/contest/465 rating+7,,简直... 感人肺腑...............蒟蒻就是蒟蒻......... 被虐瞎 a:inc ARG 题 ...

  9. Codeforces Round #265 (Div. 2) E

    这题说的是给了数字的字符串 然后有n种的操作没次将一个数字替换成另一个字符串,求出最后形成的字符串的 数字是多大,我们可以逆向的将每个数推出来,计算出他的值和位数记住位数用10的k次方来记 1位就是1 ...

随机推荐

  1. FASTQ格式

    FASQT格式是用于存储生物序列(通常是核苷酸序列)及其相应的碱基质量分数的一种文本格式.为简洁起见,序列字母和质量分数均使用单个ASCII字符进行编码.最初由Wellcome Trust Sange ...

  2. login.aspx.cs

    using System;                                                                 //指令+系统(命名空间)using Sys ...

  3. javascript 函数属性prototype(转)

    在JavaScript中并没有类的概念,但javascript中的确可以实现重载,多态,继承.这些实现其实方法都可以用JavaScript中的引用和变量作用域结合prototype来解释. 1.pro ...

  4. UVa 10534 Wavio Sequence (LIS+暴力)

    题意:给定一个序列,求一个最长子序列,使得序列长度为奇数,并且前一半严格递增,后一半严格递减. 析:先正向和逆向分别求一次LIS,然后再枚举中间的那个数,找得最长的那个序列. 代码如下: #pragm ...

  5. HDU - 6081 2017百度之星资格赛 度度熊的王国战略

    度度熊的王国战略  Accepts: 644  Submissions: 5880  Time Limit: 40000/20000 MS (Java/Others)  Memory Limit: 3 ...

  6. POJ - 3268 Silver Cow Party SPFA+SLF优化 单源起点终点最短路

    Silver Cow Party One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to ...

  7. GTK学习笔记之Linux下Gtk环境搭建

    下面介绍下Ubuntu 环境下具体的安装过程: 1.配置安装gcc/g++/gdb/make 等基本编程工具(必须装好) 刚装好的Ubuntu系统中已经有GCC了,但是这个GCC几乎什么文件都不能编译 ...

  8. 求斐波那契数列第n位的几种实现方式及性能对比(c#语言)

    在每一种编程语言里,斐波那契数列的计算方式都是一个经典的话题.它可能有很多种计算方式,例如:递归.迭代.数学公式.哪种算法最容易理解,哪种算法是性能最好的呢? 这里给大家分享一下我对它的研究和总结:下 ...

  9. java大神进阶之路

    既然励志在java路上走的更远,那就必须了解java的路径.先看图 更加细化的细节如下 一: 编程基础 不管是C还是C++,不管是Java还是PHP,想成为一名合格的程序员,基本的数据结构和算法基础还 ...

  10. ubuntu18.04安装配置boost库

    1.官网下载(www.boost.org) 2.解压并进入文件夹 3.使用命令./bootstrap.sh,可以通过加上--prefix help 4.使用命令./b2 install etc.如果运 ...