Codeforces 464E #265 (Div. 1) E. The Classic Problem 主席树+Hash
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的更多相关文章
- 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 ...
- 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 ...
- Codeforces Round #265 (Div. 2) C. No to Palindromes! 构建无回文串子
http://codeforces.com/contest/465/problem/C 给定n和m,以及一个字符串s,s不存在长度大于2的回文子串,如今要求输出一个字典比s大的字符串,且串中字母在一定 ...
- Codeforces Round #265 (Div. 2) E. Substitutes in Number
http://codeforces.com/contest/465/problem/E 给定一个字符串,以及n个变换操作,将一个数字变成一个字符串,可能为空串,然后最后将字符串当成一个数,取模1e9+ ...
- Codeforces Round #265 (Div. 2) D. Restore Cube 立方体判断
http://codeforces.com/contest/465/problem/D 给定8个点坐标,对于每个点来说,可以随意交换x,y,z坐标的数值.问说8个点是否可以组成立方体. 暴力枚举即可, ...
- Codeforces Round #265 (Div. 2) C. No to Palindromes! 构造不含回文子串的串
http://codeforces.com/contest/465/problem/C 给定n和m,以及一个字符串s,s不存在长度大于2的回文子串,现在要求输出一个字典比s大的字符串,且串中字母在一定 ...
- Codeforces Round #265 (Div. 2) D. Restore Cube 立方体推断
http://codeforces.com/contest/465/problem/D 给定8个点坐标.对于每一个点来说,能够任意交换x.y,z坐标的数值. 问说8个点能否够组成立方体. 暴力枚举就可 ...
- Codeforces Round #265 (Div. 2)
http://codeforces.com/contest/465 rating+7,,简直... 感人肺腑...............蒟蒻就是蒟蒻......... 被虐瞎 a:inc ARG 题 ...
- Codeforces Round #265 (Div. 2) E
这题说的是给了数字的字符串 然后有n种的操作没次将一个数字替换成另一个字符串,求出最后形成的字符串的 数字是多大,我们可以逆向的将每个数推出来,计算出他的值和位数记住位数用10的k次方来记 1位就是1 ...
随机推荐
- Spring Boot错误errMsg: "request:ok"
在把评论写到数据库并且动态刷新评论区的时候,有时候正常写入,有时候就会有“request:ok”的的错误出现,错误信息如下: data: {timestamp: , error: "Inte ...
- JAVA企业级开发-BOM&DOM(03)
一.BOM对象介绍 BOM对象:Browser Object Model 浏览器对象模型.把整个浏览器当做一个对象来处理. 一个浏览器对象中又包含了其他的对象. 重点介绍:window.history ...
- Python机器学习笔记:朴素贝叶斯算法
朴素贝叶斯是经典的机器学习算法之一,也是为数不多的基于概率论的分类算法.对于大多数的分类算法,在所有的机器学习分类算法中,朴素贝叶斯和其他绝大多数的分类算法都不同.比如决策树,KNN,逻辑回归,支持向 ...
- DOTween Sequence 使用图解
http://blog.csdn.net/jiejieup/article/details/41521577 最近在使用DOTween制作一些动画过渡的内容,发现非常好用,使用Sequence类可以方 ...
- 图论2 最近公共祖先LCA
模板 吸取洛谷P3379的教训,我决定换板子(其实本质都是倍增是一样的),把vector换成了边表 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下 ...
- jzoj6003. 【THUWC2019模拟2019.1.16】Square (乱搞)
题面 题解 不难发现,如果一行最后被染色,那么这行的颜色肯定一样,如果倒数第二个被染色,那么除了被最后一个染色的覆盖的那一部分剩下的颜色肯定一样 于是题目可以转化为每一次删去一行或一列颜色相同的,问最 ...
- 剑指Offer的学习笔记(C#篇)-- 从上往下打印二叉树
题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 一 . 题目解析 了解过二叉树就应该知道,二叉树存在三种遍历方法:前序遍历(根→左→右).中序遍历(左→根→右).后续遍历(左→右→根 ...
- SpringMVC 控制器写多个方法(非注解方式)
Controller类有两种方法 1,implements Controller(实现Controller接口) 2,extends MultiActionController(继承 MultiAct ...
- 管理docker容器
如果在容器中启动sshd,存在开销和攻击面增大的问题.同时也违反了Docker所倡导的一个容器一个进程的原则. docker attach 37d61466c69e \\注意:如果在stdin中exi ...
- 常用的js工具函数
JS选取DOM元素的方法注意:原生JS选取DOM元素比使用jQuery类库选取要快很多1.通过ID选取元素document.getElementById('myid');2.通过CLASS选取元素do ...