题目链接

loj#2718. 「NOI2018」归程

题解

按照高度做克鲁斯卡尔重构树

那么对于询问倍增找到当前点能到达的高度最小可行点,该点的子树就是能到达的联通快,维护子树中到1节点的最短距离

spfa她死了...同步赛没写的说...

似乎前两题比去年简单些....连蒟蒻我都可做前两题的说

代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9')c = getchar();
while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
return x * f;
}
#define mp std::make_pair
#define pr std::pair<int,int>
int n,m;
const int maxn = 1000007;
struct node {
int u,v,a,l,next;
bool operator < (const node & A)const {
return a > A.a;
}
} edge[maxn << 1],e[maxn]; int num = 0,head[maxn],dis[maxn << 1];
inline void add_edge(int u,int v,int w) { edge[++ num].v = v;edge[num].l = w;edge[num].next = head[u];head[u] = num; }
std::priority_queue<pr> q;
void dijkstar() {
static bool vis[maxn];
memset(dis,0x3f,sizeof dis); memset(vis,0,sizeof vis);
dis[1] = 0;q.push(pr(0,1));
while(!q.empty()) {
int u = q.top().second;q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u];i;i = edge[i].next) {
int v = edge[i].v;
if(dis[v] > dis[u] + edge[i].l) dis[v] = dis[u] + edge[i].l,q.push(mp(-dis[v],v));
}
}
}
int fa[maxn];
int find(int x) { if(fa[x] != x) fa[x] = find(fa[x]); return fa[x]; }
int tot = 0,dad[maxn << 1][20],mn[maxn << 1];
int lastans = 0;
int query(int x,int p) {
for(int i = 18;i >= 0;-- i) {
if(mn[dad[x][i]] > p) x = dad[x][i];
}
return dis[x];
}
void solve() {
int Q = read(),k = read(),S = read(),v,p;
if(k) while(Q --) {
v = (read() + k * lastans - 1) % n + 1;
p = (read() + k * lastans ) % (S + 1);
printf("%d\n",lastans = query(v,p)); } else while(Q --) {
v = read(),p = read();
printf("%d\n",query(v,p));
}
}
void init() {
n = read(),m = read();
//int cnt = 0;
for(int u,v,a,l,i = 1;i <= m;++ i) {
u = read(),v = read(),l = read(),a = read();
e[i].u = u,e[i].v = v,e[i].a = a;
add_edge(u,v,l); add_edge(v,u,l);
}
dijkstar();
for(int i = 1;i <= n;++ i) fa[i] = i;
tot = n;
std::sort(e + 1,e + m + 1);
int k = 1;
for(int fx,fy,i = 1;i <= m;++ i) {
int x = e[i].u,y = e[i].v,h = e[i].a;
if((fx = find(x)) == (fy = find(y))) continue;
fa[fx] = fa[fy] = dad[fx][0] = dad[fy][0] = ++ tot; fa[tot] = dad[tot][0] = tot;
mn[tot] = e[i].a; dis[tot] = std::min(dis[fx],dis[fy]);
if(++ k == n)break;
}
/*for(int i = 1;i <= tot;++ i)
for(int j = 0;dad[i][j];++ j)
dad[i][j + 1] = dad[dad[i][j]][j],mn[i][j + 1] = std::min(mn[i][j],mn[dad[i][j]][j]);
*/
for(int i = 1;i <= 18;++ i)
for(int x = 1;x <= tot;++ x)dad[x][i] = dad[dad[x][i - 1]][i - 1];
solve();
}
int main() {
freopen("return.in","r",stdin); freopen("return.out","w",stdout);
int t = read();
while(t --) {
memset(head,0,sizeof head),num = 0; lastans = 0;
init();
}
return 0;
}

loj#2718. 「NOI2018」归程的更多相关文章

  1. LOJ #2718. 「NOI2018」归程 Dijkstra+可持久化并查集

    把 $Noi2018$ day1t1 想出来还是挺开心的,虽然是一道水题~ 预处理出来 1 号点到其它点的最短路,然后预处理边权从大到小排序后加入前 $i$ 个边的并查集. 这个并查集用可持久化线段树 ...

  2. LOJ #2718. 「NOI2018」归程(Dijkstra + Kruskal重构树 + 倍增)

    题意 给你一个无向图,其中每条边有两个值 \(l, a\) 代表一条边的长度和海拔. 其中有 \(q\) 次询问(强制在线),每次询问给你两个参数 \(v, p\) ,表示在 \(v\) 出发,能开车 ...

  3. 洛谷 4768 LOJ 2718「NOI2018」归程

    [题解] 本题有多种做法,例如可持久化并查集.kruskal重构树等. kruskal重构树的做法是这样的:先把边按照海拔h从大到小的顺序排序,然后跑kruskal建立海拔的最大生成树,顺便建krus ...

  4. #2718. 「NOI2018」归程 kruskal重构树

    链接 https://loj.ac/problem/2718 思路 我们希望x所在的连通块尽量的大,而且尽量走高处 离线的话可以询问排序,kruskal过程中更新答案 在线就要用kruskal重构树 ...

  5. 「NOI2018」归程

    「NOI2018」归程 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 >\(1\) 个节点. \(m\) 条边的无向连通图(节点的编号从 \( ...

  6. LOJ #2721. 「NOI2018」屠龙勇士(set + exgcd)

    题意 LOJ #2721. 「NOI2018」屠龙勇士 题解 首先假设每条龙都可以打死,每次拿到的剑攻击力为 \(ATK\) . 这个需要支持每次插入一个数,查找比一个 \(\le\) 数最大的数(或 ...

  7. loj#2721. 「NOI2018」屠龙勇士

    题目链接 loj#2721. 「NOI2018」屠龙勇士 题解 首先可以列出线性方程组 方程组转化为在模p意义下的同余方程 因为不保证pp 互素,考虑扩展中国剩余定理合并 方程组是带系数的,我们要做的 ...

  8. Loj #2719. 「NOI2018」冒泡排序

    Loj #2719. 「NOI2018」冒泡排序 题目描述 最近,小 S 对冒泡排序产生了浓厚的兴趣.为了问题简单,小 S 只研究对 *\(1\) 到 \(n\) 的排列*的冒泡排序. 下面是对冒泡排 ...

  9. loj#2720. 「NOI2018」你的名字

    链接大合集: loj uoj luogu bzoj 单纯地纪念一下写的第一份5K代码.../躺尸 因为ZJOI都不会所以只好写NOI的题了... 总之字符串题肯定一上来就拼个大字符串跑后缀数组啦! ( ...

随机推荐

  1. G - Pandaland HDU - 6005 (找最小环)

    题目链接:https://cn.vjudge.net/contest/275153#problem/G 具体思路: 我们可以按照暴力的方法进行做 , 我们可以枚举每一条边,将这条边的权值设置为inf, ...

  2. Linux学习笔记-文件处理和权限命令

    目录 文件处理命令 touch cat tac more less head tail 链接命令 ln 权限命令 chmod 权限管理命令 chown chgrp umask 文件处理命令 touch ...

  3. 个性化你的Git Log的输出格式

    git已经变成了很多程序员日常工具之一. git log是查看git历史的好工具,不过默认的格式并不是特别的直观. 很多时候想要更简便的输出更多或者更少的信息,这里列出几个git log的format ...

  4. ADB常用命令(二)

    参考  http://adbshell.com/commands 常用命令 查看adb 版本 adb version 打印所有附加模拟器/设备的列表 adb devices 设备序列号 adb get ...

  5. poj1067

    题意:有两堆石子,两人轮流取,每次可以取一堆中的任意个,或两堆中取相同多个.谁先取光所有堆谁赢.问先手能否获胜. 分析:威佐夫博弈,如果是奇异态则先手输,否则先手赢.直接套用公式判断是否为奇异态,设第 ...

  6. Linux下获取和设置IP

    在Linux下获取关于IP和网关的操作:重点是对struct ifreq 的操作. 那么进入目录/usr/include/net/if.h下看查找struct ifreq结构体. /* Interfa ...

  7. 栈应用之 背包问题(Python 版)

    栈应用之 背包问题 背包问题描述:一个背包里可以放入重量为weight的物品,现有n件物品的集合s,其中物品的重量为别为w0,w1,...,wn-1.问题是能否从中选出若干件物品,其重量之和正好等于w ...

  8. thinkphp模型创建

  9. 通过field:global给子元素添加css样式

    {dede:arclist row=5 typeid=200} <li [field:global runphp=’yes’ name=autoindex](@me==1)?@me=”class ...

  10. JAVA复习笔记:内存结构和类加载

    Part1:JVM内存结构 JVM定义了若干个程序执行期间使用的数据区域.这个区域里的一些数据在JVM启动的时候创建,在JVM退出的时候销毁.而其他的数据依赖于每一个线程,在线程创建时创建,在线程退出 ...