zoukankan      html  css  js  c++  java
  • 【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]<<" ";
    }
    
  • 相关阅读:
    计算机组成原理:“性能”是什么?
    试题 基础练习 Huffuman树
    最小堆的插入删除函数
    特殊函数
    进程控制
    进程的描述
    进程管理
    生成和配置Linux操作系统
    系统调用
    Shell脚本编程
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328619.html
Copyright © 2011-2022 走看看