题目: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()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=2e5+,M=4e5+,INF=2e9+;
int n,m,hd[N],xnt,to[M<<],nxt[M<<],w[M<<],dis[N];
int fa[N],ht[N],mn[N],dep[N]; bool vis[N];
struct Ed{
int x,y,h;
Ed(int x=,int y=,int h=):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=,int v=):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,,sizeof vis);
for(int i=;i<=n;i++)dis[i]=INF;
q.push(mkp(,));
while(q.size())
{
int k=q.top().second; q.pop();
if(vis[k])continue; vis[k]=;
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,));
return (*it).v;
}
int main()
{
int T=rdn();
while(T--)
{
n=rdn();m=rdn();
xnt=; memset(hd,,sizeof hd);
for(int i=,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+,ed+m+);
for(int i=;i<=n;i++)
{
Mn[i].clear();
Mn[i].pb(Node(INF,mn[i]=dis[i]));
fa[i]=i; dep[i]=;
}
for(int i=;i<=m;i++)
{
int u=fnd(ed[i].x,), v=fnd(ed[i].y,);
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()+,ans=;
for(int i=,u,p;i<=Q;i++)
{
u=(rdn()+(K?ans:)-)%n+;
p=(rdn()+(K?ans:))%S;
u=fnd(u,p); ans=fnd2(u,p);
printf("%d\n",ans);
}
}
return ;
}

还写了可持久化并查集的。在 UOJ 上TLE最后两个点,在 LOJ 上能过。

注意每次 tot=0 。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define mkp make_pair
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int Mn(int a,int b){return a<b?a:b;}
const int N=2e5+,M=4e5+,K=*M,INF=;
int n,m,hd[N],xnt,to[M<<],nxt[M<<],w[M<<],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=,int y=,int h=):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,,sizeof vis);
for(int i=;i<=n;i++)dis[i]=INF;
q.push(mkp(,));
while(q.size())
{
int k=q.top().second; q.pop();
if(vis[k])continue; vis[k]=;
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]=;mn[cr]=dis[l];return;}
int mid=l+r>>;
build(l,mid,ls[cr]); build(mid+,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>>;
if(p<=mid)ins(l,mid,ls[cr],ls[pr],p);
else ins(mid+,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>>;
if(p<=mid)return qry(l,mid,ls[cr],p);
else return qry(mid+,r,rs[cr],p);
}
int fnd(int nw,int a)
{
int fa=qry(,n,nw,a);
if(vl[fa]==a)return fa;
return fnd(nw,vl[fa]);
}
int fnd2(int p)
{
int l=,r=m,ret=;//l=0
while(l<=r)
{
int mid=l+r>>;
if(ht[mid]>p)ret=mid,l=mid+;
else r=mid-;
}
return ret;
}
int main()
{
int T=rdn();
while(T--)
{
n=rdn();m=rdn();
xnt=; memset(hd,,sizeof hd);
for(int i=,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=;//////
sort(ed+,ed+m+); build(,n,rt[]);
/*
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=;
for(int i=,u,v;i<=lm;m++)
{
rt[m]=rt[m-]; 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(,n,rt[m],rt[m],vl[u]);u=tot;
ins(,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=; S++; m--; ht[]=INF;//
for(int i=,v,p;i<=Q;i++)
{
v=(rdn()+(K?ans:)-)%n+;
p=(rdn()+(K?ans:))%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 ;
}

UOJ 393 【NOI2018】归程——可持久化并查集的更多相关文章

  1. 洛谷P4768 [NOI2018]归程 [可持久化并查集,Dijkstra]

    题目传送门 归程 格式难调,题面就不放了. 分析: 之前同步赛的时候反正就一脸懵逼,然后场场暴力大战,现在呢,还是不会$Kruskal$重构树,于是就拿可持久化并查集做. 但是之前做可持久化并查集的时 ...

  2. [NOI2018] 归程 可持久化并查集

    题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个n 个节点.m 条边的无向连通图(节点的编号从 1至 n).我们依次用 l,a描述一条边的长度.海拔. ...

  3. BZOJ5415:[NOI2018]归程(可持久化并查集,最短路)

    Description Input Output Sample Input1 14 31 2 50 12 3 100 23 4 50 15 0 23 02 14 13 13 2 Sample Outp ...

  4. [NOI2018]归程(可持久化并查集,Kruskal重构树)

    解法一: 1.首先想到离线做法:将边和询问从大到小排序,并查集维护连通块以及每个连通块中所有点到1号点的最短距离.$O(n\log n)$ 配合暴力等可以拿到75分. 2.很容易想到在线做法,使用可持 ...

  5. 洛谷P4768 [NOI2018]归程(可持久化并查集,最短路)

    闲话 一个蒟蒻,在网络同步赛上进行了这样的表演-- T2组合计数不会,T3字符串数据结构不会,于是爆肝T1 一开始以为整个地图都有车,然后写了2h+的树套树,终于发现样例过不去 然后写可持久化并查集D ...

  6. [bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)

    Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0& ...

  7. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  8. bzoj3674 可持久化并查集

    我是萌萌的任意门 可持久化并查集的模板题-- 做法好像很多,可以标号法,可以森林法. 本来有O(mloglogn)的神算法(按秩合并+倍增),然而我这种鶸渣就只会写O(mlog2n)的民科算法--再加 ...

  9. 【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树

    没什么好说的. 可持久化线段树,叶子节点存放父亲信息,注意可以规定编号小的为父亲. Q:不是很清楚空间开多大,每次询问父亲操作后修改的节点个数是不确定的.. #include<bits/stdc ...

随机推荐

  1. zk请求和响应对

    zk的请求和响应是通过id对应上的: 请求头(RequestHeader)和响应头(ReplyHeader)共用一个xid,它的本质是ClientCnxn类中的一个计数器. 1. 首先看客户端: Pa ...

  2. hadoop mongodb install(3)

    reference:http://dblab.xmu.edu.cn/blog/868-2/ root@iZuf68496ttdogcxs22w6sZ:~# mv mongodb-linux-x86_6 ...

  3. System.Insert - 插入字符串

    System.Insert - 插入字符串 procedure Insert( Substr: String; {要插入的字符串; 可以是常量} var Dest: String; {源字符串} In ...

  4. 树状数组Lowbit用法

    刚学树状数组,看到这里的时候懵了.经过询问,发现,原来在程序运行时,数据用的都是补码,于是解决了 int Lowbit(x) { return x&(-x); } 如: x =1: 1 &am ...

  5. 如何高效使用Google

    摘自http://simplyy.space/ 核心思想 1.首先,想好你想要寻找什么. 哪些词能够最好地描述你要寻找的信息或者概念? 哪些词是你能够用来替换的? 有没有那些词是可以不必包括在你想要搜 ...

  6. PHP生成GIF动态图片验证码

    <?php /** * 调用示例 * */ session_start(); $randCode = ''; //验证码随机 $str="abcdefghjkmnpqrstuvwsyz ...

  7. RabbitMQ在windows下的安装

    RabbitMQ 它依赖于Erlang,需要先安装Erlang.首先确定你的window电脑是32位还是64位,以下的安装以window 64位电脑举例.   运行行Erlang/OTP(otp_wi ...

  8. Linux下Bind error: Address already in use处理

    发生这种问题是由于端口被程序绑定而没有释放造成. 可以使用netstat -lp查询当前处于连接的程序以及对应的进程信息. 如果只想查看指定端口,可以输入netstat -lp | grep 9877 ...

  9. 如何安装Magento插件

    Magento有着非常多的插件,其实就是模块,那么怎么安装需要的插件呢? 具体方法如下,以安装DeveloperToolbar这个开发插件为例讲解: 1.首先到Magento的官方网站查找到相应的插件 ...

  10. 关于XCode 的agvtool命令行

    简介:用agvtool如何来自动更新版本号和bulid version   agvtool是一个命令行工具,允许你自动递增到下一个最高的数量或具体的数字这些数字.本文档提供了更新您的构建和版本号码使用 ...