ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

#主席树,Dijkstra,哈希#CF464E The Classic Problem

2022-02-23 08:01:59  阅读:185  来源: 互联网

标签:rt Classic int CF464E rs mid Dijkstra ls heap


题目

边权均为2的幂次的无向图,求 \(S\) 到 \(T\) 的最短路

\(n,m\leq 10^5\)


分析

最短路直接考虑用 Dijkstra,它需要维护松弛操作和堆,

那么也就是要重载加号和小于号,而数字可以在主席树上维护。

对于小于号,最直接的一种做法就是从高位到低位找到第一个不同数字的位比较大小,

那么就是先在主席树上二分找到这两个数的LCP,然后比较下一位的大小,

LCP可以用哈希来维护,如果 \(base=2,mod=10^9+7\),顺便就可以把答案求出来,那么就是一个 \(\log\) 的。

对于加号,找到从第x位起第一个0,然后把左边的1都变成0,只把那个0的位置变成1,

这个维护区间左端点为开头极长的1也可以做到一个 \(\log\)

再加上堆的时间复杂度就是 \(O(m\log n\log mx+m\log mx)\)


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int mod=1000000007,N=100021; struct node{int y,w,next;}e[N<<1];
int two[N+11],pre[N],n,m,ans,as[N],S,T,rt[N],et=1,st[N],Top,v[N];
int w[N<<6],ls[N<<6],rs[N<<6],len[N<<6],cnt,Cnt; pair<int,int>heap[N<<1];
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
void build(int &rt,int l,int r){
	rt=++cnt;
	if (l==r) return;
	int mid=(l+r)>>1;
	build(ls[rt],l,mid);
	build(rs[rt],mid+1,r);
}
bool geq(int fi,int se,int l,int r){
	if (w[fi]==w[se]) return 0;
	if (l==r) return w[fi]>w[se];
	int mid=(l+r)>>1;
	if (w[rs[fi]]==w[rs[se]]) return geq(ls[fi],ls[se],l,mid);
	    else return geq(rs[fi],rs[se],mid+1,r);
}
int zero(int rt,int l,int r,int x,int y){
	if (l==x&&r==y){
		if (len[rt]==r-l+1) return 0x3f3f3f3f;
		    else return l+len[rt];
	}
	int mid=(l+r)>>1;
	if (y<=mid) return zero(ls[rt],l,mid,x,y);
	else if (x>mid) return zero(rs[rt],mid+1,r,x,y);
	else{
		int now=zero(ls[rt],l,mid,x,mid);
		if (now!=0x3f3f3f3f) return now;
		    else return zero(rs[rt],mid+1,r,mid+1,y);
	}
}
void upd(int &rt,int l,int r,int x){
	int trt=++cnt;
	ls[trt]=ls[rt],rs[trt]=rs[rt],rt=trt;
	if (l==r){
		len[rt]=w[rt]=1;
		return;
	}
	int mid=(l+r)>>1;
	if (x<=mid) upd(ls[rt],l,mid,x);
	    else upd(rs[rt],mid+1,r,x);
	w[rt]=(w[ls[rt]]+1ll*w[rs[rt]]*two[mid-l+1]%mod)%mod;
	if (len[ls[rt]]==mid-l+1) len[rt]=len[ls[rt]]+len[rs[rt]];
	    else len[rt]=len[ls[rt]];
}
void update(int &rt,int Rt,int l,int r,int x,int y){
	if (l==x&&r==y) {rt=Rt; return;}
	else{
		int trt=++cnt;
		ls[trt]=ls[rt],rs[trt]=rs[rt],rt=trt;
	}
    int mid=(l+r)>>1;
    if (y<=mid) update(ls[rt],ls[Rt],l,mid,x,y);
    else if (x>mid) update(rs[rt],rs[Rt],mid+1,r,x,y);
    else{
    	update(ls[rt],ls[Rt],l,mid,x,mid);
    	update(rs[rt],rs[Rt],mid+1,r,mid+1,y);
	}
	w[rt]=(w[ls[rt]]+1ll*w[rs[rt]]*two[mid-l+1]%mod)%mod;
	if (len[ls[rt]]==mid-l+1) len[rt]=len[ls[rt]]+len[rs[rt]];
	    else len[rt]=len[ls[rt]];
}
void add(int &Rt,int x){
	int now=zero(Rt,0,N,x,N);
	upd(Rt,0,N,now);
	if (x<now) update(Rt,rt[S],0,N,x,now-1);
}
void Pop(){
	heap[1]=heap[Cnt--];
	for (int x=1;(x<<1)<=Cnt;){
		int y=x<<1|1;
		if (y>Cnt||geq(heap[y].first,heap[y-1].first,0,N)) --y;
		if (geq(heap[x].first,heap[y].first,0,N)) swap(heap[x],heap[y]),x=y;
		    else break;
	}
}
void Push(pair<int,int> x){
	heap[++Cnt]=x;
	for (int x=Cnt;x>1;x>>=1)
	if (geq(heap[x>>1].first,heap[x].first,0,N))
	    swap(heap[x],heap[x>>1]);
	else break;
}
void Dijkstra(int S){
	heap[Cnt=1]=make_pair(rt[S],S),build(rt[S],0,N);
	while (Cnt){
		while (Cnt&&v[heap[1].second]) Pop();
		if (!Cnt) return;
		int x=heap[1].second; v[x]=1,Pop();
		for (int i=as[x],Rt;i;i=e[i].next)
		if (!v[e[i].y]){
			int CNT=cnt;
			add(Rt=rt[x],e[i].w);
			if (!rt[e[i].y]||geq(rt[e[i].y],Rt,0,N)){
				rt[e[i].y]=Rt,pre[e[i].y]=x;
				Push(make_pair(Rt,e[i].y));
			}else for (;cnt>CNT;--cnt) w[cnt]=len[cnt]=ls[cnt]=rs[cnt]=0;
		}
	}
}
int main(){
	n=iut(),m=iut(),two[0]=1;
	if (n==1) return !printf("0\n1\n1");
	for (int i=1;i<=N;++i) two[i]=2ll*two[i-1]%mod;
	for (int i=1;i<=m;++i){
		int x=iut(),y=iut(),w=iut();
		e[++et]=(node){y,w,as[x]},as[x]=et;
		e[++et]=(node){x,w,as[y]},as[y]=et;
	}
	S=iut(),T=iut(),Dijkstra(S);
	if (pre[T]){
		for (int _T=T;_T;_T=pre[_T]) st[++Top]=_T;
		printf("%d\n%d\n",w[rt[T]],Top);
		for (int i=Top;i;--i)
		    printf("%d%c",st[i],i==1?10:32);
	}else printf("-1");
	return 0;
}

标签:rt,Classic,int,CF464E,rs,mid,Dijkstra,ls,heap
来源: https://www.cnblogs.com/Spare-No-Effort/p/15925743.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有