[最短路 && 主席树维护HASH]Codeforces 464E. The Classic Problem

传送门
老套路
51nod1863一样。
就是多了进位

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <assert.h>
#define fi first
#define se second

using namespace std;

typedef unsigned int ll;

typedef pair<int,int> ii;

const int N=100105,P1=1e9+7,P2=1e9+9,MAX=100100;
const ll base=100003;

bool bg;

int n,m,cnt,cnt0,g,rt[N*280],ls[N*280],rs[N*280],tag[N*280],G[N],len[N];
ll pw[N],v[N*280],p[N];
struct edge{
  int t,nx,w;
}E[N<<1];

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void rea(int &x){
  char c=nc(); x=0;
  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

inline void set1(int &g,int l,int r){
  int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; v[g]=v[k];
 v[g]=p[r-l]; tag[g]=1;
}

inline void set0(int &g,int l,int r){
  int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; v[g]=v[k];
  v[g]=0; tag[g]=0;
}

inline void Push(int &g,int L,int R){
  if(~tag[g]){
    int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; v[g]=v[k];
    int mid=L+R>>1;
    if(tag[g])
      set1(ls[g],L,mid),set1(rs[g],mid+1,R);
    else
      set0(ls[g],L,mid),set0(rs[g],mid+1,R);
    tag[g]=-1;
  }
}

inline bool cmp(int &a,int &b,int l,int r){
  if(v[a]==0 && v[b]) return true;
  if(v[a] && v[b]==0) return false;
  if(v[a]==v[b]) return false;
  if(l==r) return v[a]<v[b];
  if(tag[a]!=-1 || tag[b]!=-1)
    int sss=0;
  assert(tag[a]==-1 && tag[b]==-1);
  int mid=l+r>>1;
  if(v[ls[a]]==v[ls[b]])
    return cmp(rs[a],rs[b],mid+1,r);
  else
    return cmp(ls[a],ls[b],l,mid);
}

struct U{
  int x,y;
  friend bool operator ==(U a,U b){
    return v[a.y]==v[b.y];
  }
  friend bool operator <(U a,U b){
    if(v[a.y]==v[b.y]) return false;
    return !cmp(a.y,b.y,1,MAX);
  }
};

priority_queue<U> Q;

int Find(int &g,int l,int r,int L,int R){
  if(v[g]==0) return r;
  if(v[g]==p[R-L]) return -1;
  if(!g) return r;
  if(L==R) return v[g]?-1:L;
  int mid=L+R>>1; 
  if(l==L && r==R){
    if(v[rs[g]]!=p[R-mid-1]) return Find(rs[g],mid+1,r,mid+1,R);
    return Find(ls[g],l,mid,L,mid);
  }
  if(r<=mid) return Find(ls[g],l,r,L,mid);
  else if(l>mid) return Find(rs[g],l,r,mid+1,R);
  int ret=Find(rs[g],mid+1,r,mid+1,R);
  if(~ret) return ret;
  return Find(ls[g],l,mid,L,mid);
}

inline void Up(int g,int l){
  v[g]=v[ls[g]]*pw[l]+v[rs[g]];
}

void Cover(int &g,int l,int r,int L,int R){
  int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; v[g]=v[k];
  if(l==L && r==R) return set0(g,L,R);
  int mid=L+R>>1; Push(g,L,R);
  if(r<=mid) Cover(ls[g],l,r,L,mid);
  else if(l>mid) Cover(rs[g],l,r,mid+1,R);
  else Cover(ls[g],l,mid,L,mid),Cover(rs[g],mid+1,r,mid+1,R);
  Up(g,R-mid);
}

void Modify(int &g,int x,int L,int R){
  int k=g; g=++cnt; ls[g]=ls[k]; rs[g]=rs[k]; tag[g]=tag[k]; v[g]=v[k];
  if(L==R) return set1(g,L,R);
  int mid=L+R>>1; Push(g,L,R);
  if(x<=mid) Modify(ls[g],x,L,mid);else Modify(rs[g],x,mid+1,R);
  Up(g,R-mid);
}

int ans,ss,tt,frm[N];

void dfs(int &g,int l,int r){
  if(l==r){
    ans=(2LL*ans+v[g])%P1;
    return ;
  }
  int mid=l+r>>1; Push(g,l,r);
  dfs(ls[g],l,mid); dfs(rs[g],mid+1,r);
}

int prnt[N],pnt;

inline void add(int x,int y,int z){
  E[++cnt0].t=y; E[cnt0].nx=G[x]; E[cnt0].w=z; G[x]=cnt0;
  E[++cnt0].t=x; E[cnt0].nx=G[y]; E[cnt0].w=z; G[y]=cnt0;
}
bool ed;

int main(){
  pw[0]=p[0]=1; for(int i=1;i<=MAX;i++) p[i]=p[i-1]+(pw[i]=pw[i-1]*base);
  rea(n); rea(m);
  memset(tag,-1,sizeof(tag));
  for(int i=1;i<=m;i++){
    int x,y,z; rea(x); rea(y); rea(z);
    add(x,y,z);
  }
  int ss,tt; rea(ss); rea(tt);
  Cover(rt[ss],1,MAX,1,MAX);
  Q.push(U{ss,rt[ss]});
  while(!Q.empty()){
    int x=Q.top().x,y=Q.top().y; Q.pop();
    if(y!=rt[x]) continue;
    for(int i=G[x];i;i=E[i].nx){
      int u=E[i].t,val=MAX-E[i].w,cur=y,lst=cnt,cg=0;
      int pos=Find(cur,1,val,1,MAX);
      if(pos+1<=val) Cover(cur,pos+1,val,1,MAX);
      Modify(cur,pos,1,MAX); int r=rt[u];
      if(!r || cmp(cur,r,1,MAX)){
    cg=1; rt[u]=cur; frm[u]=x; Q.push(U{u,rt[u]});
      }
      if(!cg) cnt=lst;
    }
  }
  if(!rt[tt]) puts("-1");
  else{
    dfs(rt[tt],1,MAX);
    printf("%d\n",ans);
    while(tt){
      prnt[++pnt]=tt; tt=frm[tt];
    }
    printf("%d\n",pnt);
    for(int i=pnt;i;i--) printf("%d ",prnt[i]);
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值