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. 由sock引起的感想

    昨天晚上和同学聊天,他问我你敲了这么多TCP,UDP.到底掌握了什么,我说我敲了很多例子.对这两个模式很清晰,顺便练习了多进程,线程等等. 他说,这样不太好.我一直只是拿这两个例子在练习,没有真正的在 ...

  2. The web.config file for this project is missing the required DirectRequestModule.

    The web.config file for this project is missing the required DirectRequestModule.   将应用程序集的模式由集成改为经典 ...

  3. css hack汇总

    注意点: 网上很多资料中常常把!important也作为一个hack手段,其实这是一个误区.!important常常被我们用来更改样式,而不是兼容hack.造成这个误区的原因是IE6在某些情况下不主动 ...

  4. React 从入门到进阶之路(五)

    之前的文章我们介绍了  React 事件,方法, React定义方法的几种方式 获取数据 改变数据 执行方法传值.接下来我们将介绍 React 表单事件 键盘事件 事件对象以及 React中 的 re ...

  5. Angular中依赖注入方式的几种写法

    1.第一种写法 angular.module('App').controller('TestCtrl',['$scope', function($scope) {}]); 2.第二种写法 angula ...

  6. 渲染路径-Unity5 的新旧推迟渲染Deferred Lighting Rendering Path

    Unity5 的新旧延迟渲染Deferred Lighting Rendering Path unity5 的render path ,比4的区别就是使用的新的deferred rendering,之 ...

  7. 求10000以内n的阶乘(openjudge 2923)

    求10000以内n的阶乘 总时间限制:  5000ms 内存限制:  655360kB 描述 求10000以内n的阶乘. 输入 只有一行输入,整数n(0<=n<=10000). 输出 一行 ...

  8. C - Distinct Substrings (模板)

    https://vjudge.net/problem/SPOJ-DISUBSTR 有两种方式来求去除重读的子串 #include <bits/stdc++.h> using namespa ...

  9. Codeforces 1141F2(贪心、预处理)

    要点 一开始dp然后码力太辣鸡并且算法带假于是调了很久一交还WA在28-- 吐槽完毕.后来想拿栈优化dp时发现其实完全不需要dp,贪心选取即可,当前的不兼容就干脆不要它了,结果不会变差.然后想要什么就 ...

  10. 如何安装使用windows自带的telnet服务

    控制面板->程序和功能->打开或关闭Windows功能->Telnet 客户端 [ Telnet 服务器 ] 安装完成后重启cmd telnet ip port