【NOI2018】归程

题面

https://www.luogu.org/problem/P4768

题解

#include<cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;

int dis[205000];
bool vis[205000];

inline int read() {
  int x=0,f=1;char c=getchar();
  while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
  while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
  return x*f;
}

struct node {
  int lb,rb,lson,rson,fa,mindis,dep;
} tree[20000500];

struct edge {
  int u,v,l,h;
  bool operator < (const edge rhs) const {
    return h<rhs.h;
  }
} a[405000];

struct node2 {
  int u,d;
  bool operator < (const node2 rhs) const {
    return d>rhs.d;
  }
};

vector<int> to[205000],len[205000];

int n,m,cnt,root[405000];

void dij() {
  register int i;
  priority_queue<node2> pq;
  while (!pq.empty()) pq.pop();
  dis[1]=0;
  for (i=2;i<=n;i++) dis[i]=2e9+5;
  memset(vis,0,sizeof(vis));
  pq.push((node2){1,0});
  while (!pq.empty()) {
    node2 x=pq.top(); pq.pop();
    if (vis[x.u]) continue;
    dis[x.u]=x.d;
    vis[x.u]=true;
    for (i=to[x.u].size()-1;i>=0;i--) if (x.d+len[x.u][i]<dis[to[x.u][i]]) {
      dis[to[x.u][i]]=x.d+len[x.u][i];
      pq.push((node2){to[x.u][i],dis[to[x.u][i]]});
    }
  }
}

void maketree(register int now,register int l,register int r){
  tree[now].lb=l; tree[now].rb=r;
  if (l==r) {
    tree[now].fa=l;
    tree[now].mindis=dis[l];
    tree[now].dep=1;
    return;
  }
  // fa to a loc
  register int mid=(l+r)/2;
  tree[now].lson=cnt+1;
  maketree(++cnt,l,mid);
  tree[now].rson=cnt+1;
  maketree(++cnt,mid+1,r);
}

void build(register int now,register int old,register int uu,register int vv) {
  tree[now]=tree[old];
  register int l=tree[now].lb,r=tree[now].rb,mid=(l+r)/2;
  if (l==r) return;
  if ((l<=uu&&uu<=mid)||(l<=vv&&vv<=mid)) 
    tree[now].lson=cnt+1,build(++cnt,tree[old].lson,uu,vv);
  if ((mid+1<=uu&&uu<=r)||(mid+1<=vv&&vv<=r))
    tree[now].rson=cnt+1,build(++cnt,tree[old].rson,uu,vv);
}

int find(register int now,register int loc) { //return a poregister int
  if (tree[now].lb==tree[now].rb) return now;
  if (loc<=(tree[now].lb+tree[now].rb)/2) 
  return find(tree[now].lson,loc);
  else return find(tree[now].rson,loc);
}

int findroot(register int now,register int cur) { //return a loc
  if (tree[now].fa==tree[now].lb) return tree[now].lb; 
    else return findroot(find(root[cur],tree[now].fa),cur);
}

void kru(){
  register int i,j,uu,vv;
  sort(a+1,a+m+1);
  cnt=0;
  root[m+1]=1;
  maketree(++cnt,1,n);
  for (i=m;i>=1;i--) {
    uu=findroot(find(root[i+1],a[i].u),i+1);
    vv=findroot(find(root[i+1],a[i].v),i+1);
    if (uu==vv) {
      root[i]=root[i+1];
      continue;
    }
    root[i]=cnt+1;
    build(++cnt,root[i+1],uu,vv);
    uu=find(root[i],uu);
    vv=find(root[i],vv);

    if (tree[uu].dep<tree[vv].dep) {
      tree[vv].dep=max(tree[vv].dep,tree[uu].dep+1);
      tree[vv].mindis=min(tree[vv].mindis,tree[uu].mindis);
      tree[uu].fa=tree[vv].lb;
    }
    else {
    tree[uu].dep=max(tree[uu].dep,tree[vv].dep+1);
      tree[uu].mindis=min(tree[uu].mindis,tree[vv].mindis);
      tree[vv].fa=tree[uu].lb;
    }
  }
}

int main(){
  register int T,i,j,v,q,k,s,p,lastans;
  T=read();
  while (T--) {
    n=read(); m=read();
    for (i=1;i<=n;i++) to[i].clear(),len[i].clear();
    for (i=1;i<=m;i++) {
    a[i].u=read(); a[i].v=read(); a[i].l=read(); a[i].h=read();
      to[a[i].u].push_back(a[i].v); len[a[i].u].push_back(a[i].l);
      to[a[i].v].push_back(a[i].u); len[a[i].v].push_back(a[i].l);
    }
    dij();
    kru();
    q=read(); k=read(); s=read();
    lastans=0;
    a[m+1].h=2e9+5;
    for (i=1;i<=q;i++) {
      v=read(); p=read();
      v=(v+k*lastans-1)%n+1;
      p=(p+k*lastans)%(s+1);
      register int cur=upper_bound(a+1,a+m+2,(edge){0,0,0,p})-a;
      register int ans=find(root[cur],findroot(find(root[cur],v),cur));
      printf("%d
",tree[ans].mindis);
      lastans=tree[ans].mindis;
    }
  }
}
原文地址:https://www.cnblogs.com/shxnb666/p/11275457.html