UOJ 393 【NOI2018】歸程——可持久化並查集
阿新 • • 發佈:2019-02-15
sed while urn ocr noi pan algo node --
題目:http://uoj.ac/problem/393
題解:https://www.cnblogs.com/HocRiser/p/9368067.html
但過不了 UOJ 的 hack 數據。不知道是哪裏出錯。之後再管吧。
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> #define mkp make_pair #define pb push_back using namespace std; int rdn() {View Codeint ret=0;bool fx=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)fx=0;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘)ret=ret*10+ch-‘0‘,ch=getchar(); return fx?ret:-ret; } const int N=2e5+5,M=4e5+5,INF=2e9+5; int n,m,hd[N],xnt,to[M<<1],nxt[M<<1],w[M<<1],dis[N]; intfa[N],ht[N],mn[N],dep[N]; bool vis[N]; struct Ed{ int x,y,h; Ed(int x=0,int y=0,int h=0):x(x),y(y),h(h) {} bool operator< (const Ed &b)const {return h>b.h;} }ed[M]; struct Node{ int h,v; Node(int h=0,int v=0):h(h),v(v) {} bool operator< (const Node &b)const {return h>b.h;} }; priority_queue<pair<int,int> > q; vector<Node> Mn[N]; vector<Node>::iterator it; void add(int x,int y,int z){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;} void dj() { memset(vis,0,sizeof vis); for(int i=2;i<=n;i++)dis[i]=INF; q.push(mkp(0,1)); while(q.size()) { int k=q.top().second; q.pop(); if(vis[k])continue; vis[k]=1; for(int i=hd[k],v;i;i=nxt[i]) if(dis[v=to[i]]>dis[k]+w[i]) { dis[v]=dis[k]+w[i]; q.push(mkp(-dis[v],v)); } } } int fnd(int u,int p) { while(fa[u]!=u&&ht[u]>p)u=fa[u]; return u; } int fnd2(int u,int p) { it=--lower_bound(Mn[u].begin(),Mn[u].end(),Node(p,0)); return (*it).v; } int main() { int T=rdn(); while(T--) { n=rdn();m=rdn(); xnt=0; memset(hd,0,sizeof hd); for(int i=1,u,v,l,h;i<=m;i++) { u=rdn();v=rdn();l=rdn();h=rdn(); add(u,v,l);add(v,u,l); ed[i]=Ed(u,v,h); } dj(); sort(ed+1,ed+m+1); for(int i=1;i<=n;i++) { Mn[i].clear(); Mn[i].pb(Node(INF,mn[i]=dis[i])); fa[i]=i; dep[i]=1; } for(int i=1;i<=m;i++) { int u=fnd(ed[i].x,0), v=fnd(ed[i].y,0); if(u==v)continue; if(dep[u]>dep[v])swap(u,v); if(dep[u]==dep[v])dep[v]++; fa[u]=v; ht[u]=ed[i].h; if(mn[u]<mn[v]) Mn[v].pb(Node(ed[i].h,mn[v]=mn[u])); } int Q=rdn(),K=rdn(),S=rdn()+1,ans=0; for(int i=1,u,p;i<=Q;i++) { u=(rdn()+(K?ans:0)-1)%n+1; p=(rdn()+(K?ans:0))%S; u=fnd(u,p); ans=fnd2(u,p); printf("%d\n",ans); } } return 0; }
還寫了可持久化並查集的。在 UOJ 上TLE最後兩個點,在 LOJ 上能過。
註意每次 tot=0 。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define mkp make_pair using namespace std; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)fx=0;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘)ret=ret*10+ch-‘0‘,ch=getchar(); return fx?ret:-ret; } int Mn(int a,int b){return a<b?a:b;} const int N=2e5+5,M=4e5+5,K=36*M,INF=2147483647; int n,m,hd[N],xnt,to[M<<1],nxt[M<<1],w[M<<1],dis[N]; int tp[M],rt[M],ht[M]; bool vis[N]; int tot,ls[K],rs[K],vl[K],dep[K],mn[K]; struct Ed{ int x,y,h; Ed(int x=0,int y=0,int h=0):x(x),y(y),h(h) {} bool operator< (const Ed &b)const {return h>b.h;} }ed[M]; priority_queue<pair<int,int> > q; void add(int x,int y,int z) {to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;} void dj() { memset(vis,0,sizeof vis); for(int i=2;i<=n;i++)dis[i]=INF; q.push(mkp(0,1)); while(q.size()) { int k=q.top().second; q.pop(); if(vis[k])continue; vis[k]=1; for(int i=hd[k],v;i;i=nxt[i]) if(dis[v=to[i]]>dis[k]+w[i]) dis[v]=dis[k]+w[i], q.push(mkp(-dis[v],v)); } } void build(int l,int r,int& cr) { cr=++tot; if(l==r){vl[cr]=l;dep[cr]=1;mn[cr]=dis[l];return;} int mid=l+r>>1; build(l,mid,ls[cr]); build(mid+1,r,rs[cr]); } void ins(int l,int r,int& cr,int pr,int p) { cr=++tot;ls[cr]=ls[pr];rs[cr]=rs[pr]; if(l==r) { vl[cr]=vl[pr];dep[cr]=dep[pr]; mn[cr]=mn[pr];return; } int mid=l+r>>1; if(p<=mid)ins(l,mid,ls[cr],ls[pr],p); else ins(mid+1,r,rs[cr],rs[pr],p); } int qry(int l,int r,int cr,int p) { if(l==r)return cr; int mid=l+r>>1; if(p<=mid)return qry(l,mid,ls[cr],p); else return qry(mid+1,r,rs[cr],p); } int fnd(int nw,int a) { int fa=qry(1,n,nw,a); if(vl[fa]==a)return fa; return fnd(nw,vl[fa]); } int fnd2(int p) { int l=0,r=m,ret=0;//l=0 while(l<=r) { int mid=l+r>>1; if(ht[mid]>p)ret=mid,l=mid+1; else r=mid-1; } return ret; } int main() { int T=rdn(); while(T--) { n=rdn();m=rdn(); xnt=0; memset(hd,0,sizeof hd); for(int i=1,u,v,l,a;i<=m;i++) { u=rdn();v=rdn();l=rdn();a=rdn(); add(u,v,l); add(v,u,l); ed[i]=Ed(u,v,a); tp[i]=a; } dj(); int Q=rdn(),K=rdn(),S=rdn(); tot=0;////// sort(ed+1,ed+m+1); build(1,n,rt[0]); /* for(int i=1,u,v;i<=m;i++) { rt[i]=rt[i-1]; u=fnd(rt[i],ed[i].x); v=fnd(rt[i],ed[i].y); if(vl[u]==vl[v])continue; if(dep[u]>dep[v])swap(u,v); ins(1,n,rt[i],rt[i],vl[u]);u=tot; ins(1,n,rt[i],rt[i],vl[v]);v=tot; vl[u]=vl[v]; mn[v]=Mn(mn[v],mn[u]); if(dep[u]==dep[v])dep[v]++; } */ int lm=m; m=1; for(int i=1,u,v;i<=lm;m++) { rt[m]=rt[m-1]; ht[m]=ed[i].h; while(i<=lm&&ed[i].h==ht[m]) { u=fnd(rt[m],ed[i].x); v=fnd(rt[m],ed[i].y); i++; if(vl[u]==vl[v])continue; if(dep[u]>dep[v])swap(u,v); ins(1,n,rt[m],rt[m],vl[u]);u=tot; ins(1,n,rt[m],rt[m],vl[v]);v=tot; vl[u]=vl[v]; mn[v]=Mn(mn[v],mn[u]); if(dep[u]==dep[v])dep[v]++; } } int ans=0; S++; m--; ht[0]=INF;// for(int i=1,v,p;i<=Q;i++) { v=(rdn()+(K?ans:0)-1)%n+1; p=(rdn()+(K?ans:0))%S; p=fnd2(p); //p=lower_bound(ed+1,ed+m+1,Ed(0,0,p))-ed-1; v=fnd(rt[p],v); ans=mn[v]; printf("%d\n",ans); } } return 0; }View Code
UOJ 393 【NOI2018】歸程——可持久化並查集