【Codeforces Round #265 (Div. 1)】E—The Classic Problem(主席树+最短路+哈希)

传送门


用主席树维护距离的二进制位
处理进位可以二分第一个为0的地方
比较大小的话可以通过哈希找到第一个不同的地方

复杂度O(mlog2n)O(mlog^2n)

主席树多开loglog个位置处理进位

写的单哈希被卡了
于是写了个双哈希

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define ull unsigned long long
const int mod=1e9+7,g=3;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a=add(a,b);}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline void Dec(int &a,int b){a=dec(a,b);}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=100505;
cs ull mod1=1004535809;
cs ull mod2=2281701377;
ull bas1,bas2;
ull pw1[N],pw2[N];
int mx,bin[N];
namespace Pt{
	cs int M=N*200;
	ull has1[M],has2[M];
	int lc[M],rc[M],siz[M],tot;
	#define mid ((l+r)>>1)
	inline void pushup(int u,int l,int r){
		siz[u]=siz[lc[u]]+siz[rc[u]];
		has1[u]=(has1[lc[u]]*pw1[mid-l+1]%mod1+has1[rc[u]])%mod1;
		has2[u]=(has2[lc[u]]*pw2[mid-l+1]%mod2+has2[rc[u]])%mod2;
	}
	inline void insert(int r1,int &u,int l,int r,int p){
		u=++tot;
		siz[u]=siz[r1]+1,lc[u]=lc[r1],rc[u]=rc[r1];
		if(l==r){has1[u]=l,has2[u]=l;return;}
		if(p<=mid)insert(lc[r1],lc[u],l,mid,p);
		else insert(rc[r1],rc[u],mid+1,r,p);
		pushup(u,l,r);
	}
	inline int find(int r1,int r2,int l,int r){
		if(l==r){return siz[r1]>=siz[r2];}
		if(has1[rc[r1]]!=has1[rc[r2]]||has2[rc[r1]]!=has2[rc[r2]])return find(rc[r1],rc[r2],mid+1,r);
		return find(lc[r1],lc[r2],l,mid);
	} 
	inline int comp(int a,int b){
		int k=find(a,b,0,mx);
		if(k==1)return true;
		else return false;
	}
	inline void delet(int r1,int &u,int l,int r,int st,int des){
		if(!u)return;
		if(st<=l&&r<=des){u=0;return;}
		u=++tot;lc[u]=lc[r1],rc[u]=rc[r1],siz[u]=siz[r1];
		if(st<=mid)delet(lc[r1],lc[u],l,mid,st,des);
		if(mid<des)delet(rc[r1],rc[u],mid+1,r,st,des);
		pushup(u,l,r);
	}
	inline int query(int u,int l,int r,int st,int des){
		if(!u)return 0;
		if(st<=l&&r<=des)return siz[u];
		int res=0;
		if(st<=mid)res+=query(lc[u],l,mid,st,des);
		if(mid<des)res+=query(rc[u],mid+1,r,st,des);
		return res;
	}
	inline int goup(int u,int p){
		int k=query(u,0,mx,p,p);
		if(!k){insert(u,u,0,mx,p);return u;}
		int L=p+1,R=mx,res=mx;
		while(L<=R){
			int mi=(L+R)>>1 ;
			if(query(u,0,mx,p+1,mi)==mi-p)L=mi+1;
			else R=mi-1,res=mi;
		}
		delet(u,u,0,mx,p,res-1);
		insert(u,u,0,mx,res);
		return u;
	}
	inline int calc(int u,int l,int r){
		if(!u) return 0;
		if(l==r)return bin[l];
		return add(calc(lc[u],l,mid),calc(rc[u],mid+1,r));
	}
}
using namespace Pt;
struct node{
	int x,y;
	friend inline bool operator <(cs node &a,cs node &b){
		return comp(a.x,b.x);
	}
};
priority_queue<node> q;
int n,m,str,des,dis[N],pre[N],vis[N];
int adj[N],nxt[N<<1],to[N<<1],val[N<<1],cnt;
inline void add(int u,int v,int w){
	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
}
inline void dijkstra(){
	dis[str]=++tot,q.push(node{dis[str],str});
	while(!q.empty()){
		int u=q.top().y;q.pop();
		if(vis[u])continue;
		vis[u]=1;
		for(int e=adj[u];e;e=nxt[e]){
			int v=to[e],k=goup(dis[u],val[e]);
			if(!dis[v]||comp(dis[v],k)){
				dis[v]=k,pre[v]=u;
				q.push(node{dis[v],v});
			}
		}
	}
}
int ans[N*20],top;
int main(){
	srand(time(NULL));
	bas1=rand(),bas2=rand();
	n=read(),m=read();
	for(int i=1;i<=m;i++){
		int u=read(),v=read(),w=read();
		add(u,v,w),add(v,u,w);
		chemx(mx,w);
	}
	mx+=100;
	pw1[0]=pw2[0]=bin[0]=1;
	for(int i=1;i<N;i++)pw1[i]=pw1[i-1]*bas1%mod1,pw2[i]=pw2[i-1]*bas2%mod2,bin[i]=mul(bin[i-1],2);
	str=read(),des=read();
	dijkstra();
	if(!dis[des]){return puts("-1"),0;}
	cout<<calc(dis[des],0,mx)<<'
';
	ans[top=1]=des;
	for(int i=des;i!=str;)i=pre[i],ans[++top]=i;
	cout<<top<<'
';
	for(int i=top;i;i--)cout<<ans[i]<<" ";
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328619.html