线段树优化建图,用于区间到区间建边时降低空间复杂度

建立两颗线段树,一颗in, 代表进入这个区间,一颗out,代表从这个区间出去

in树从父亲向儿子建边,代表宏观进入整个区间,不向下寻找

out树从儿子向父亲建边,代表出去

in树向out树对应点建边,代表从这个点进去可以从它出去

建真正的边时:

1: 单点向单点: out树对应点向in树对应点建边

2: 单点向区间: out树对应点向in树对应区间建边

3: 区间向单点: out树对应区间向in树对应点建边

4: 区间向区间: out树区间对新点P建边,P向in树对应点建边

cf787D

最短路裸题

#include <bits/stdc++.h>
using namespace std; const int N = 1e5 + 10;
using LL = long long;
vector<pair<int,int>> G[N << 3];
int in[N << 2], out[N << 2], pos[N], n, q, s, t, v, u, l, r, w, tot;
LL dis[N << 3]; inline void add(int x, int y, int v) {
G[x].push_back(make_pair(y, v));
} void build_in(int rt, int l, int r) {
if(l == r) {
pos[l] = rt;
return;
}
int mid = l + r >> 1;
build_in(rt << 1, l, mid);
build_in(rt << 1 | 1, mid + 1, r);
add(rt, rt << 1, 0); //in树父亲向儿子建边
add(rt, rt << 1 | 1, 0);
} void build_out(int rt, int l, int r) {
add(rt, tot + rt, 0); //in树向out树建边
if(l == r) {
return;
}
int mid = l + r >> 1;
build_out(rt << 1, l, mid);
build_out(rt << 1 | 1, mid + 1, r);
add(tot + (rt << 1), tot + rt, 0); //out树儿子向父亲建边
add(tot + (rt << 1 | 1), tot + rt, 0);
} void update_in(int rt, int l, int r, int L, int R, int from, int val) {
if(L <= l && r <= R) {
add(tot + pos[from], rt, val);
return;
}
int mid = l + r >> 1;
if(L <= mid)
update_in(rt << 1, l, mid, L, R, from, val);
if(mid < R)
update_in(rt << 1 | 1, mid + 1, r, L, R, from, val);
} void update_out(int rt, int l, int r, int L, int R, int pnt, int val) {
if(L <= l && r <= R) {
add(tot + rt, pos[pnt], val);
return;
}
int mid = l + r >> 1;
if(L <= mid)
update_out(rt << 1, l, mid, L, R, pnt, val);
if(mid < R)
update_out(rt << 1 | 1, mid + 1, r, L, R, pnt, val);
} struct node {
LL dis;
int id;
bool operator<(const node &rhs) const {
return dis > rhs.dis;
}
}; void dijk() {
memset(dis, 0x3f, sizeof(dis));
dis[pos[s]] = 0;
priority_queue<node> pq;
pq.push({0, pos[s]});
while(!pq.empty()) {
node u = pq.top();
pq.pop();
if(dis[u.id] < u.dis) continue;
for(auto &j: G[u.id]) {
if(dis[j.first] > u.dis + j.second) {
dis[j.first] = u.dis + j.second;
pq.push({dis[j.first], j.first});
}
}
}
} int main() {
scanf("%d%d%d", &n, &q, &s);
tot = n << 2;
build_in(1, 1, n);
build_out(1, 1, n);
while(q--) {
scanf("%d", &t);
if(t == 1) { //v->u
scanf("%d%d%d", &v, &u, &w);
add(pos[v] + tot, pos[u], w);
}
if(t == 2) { //v->[l,r]
scanf("%d%d%d%d", &v, &l, &r, &w);
update_in(1, 1, n, l, r, v, w);
}
if(t == 3) { //[l,r]->v
scanf("%d%d%d%d", &v, &l, &r, &w);
update_out(1, 1, n, l, r, v, w);
}
}
dijk();
for(int i = 1; i <= n; ++i) {
printf("%lld%c", dis[pos[i]] == 0x3f3f3f3f3f3f3f3f ? -1 : dis[pos[i]], " \n"[i == n]);
} return 0;
}

2019Wannafly Winter Camp Day7 Div1 E

给你线性探查法哈希后的序列,求字典序最小的原序列

记一个数应该在的位置为\(pos\), 实际在的位置为\(s\),那么\(pos\)到\(s-1\)(模\(n\)意义下的)这些位置的数肯定在\(s\)前被插入

建边拓扑排序就行了,要求字典序最小就用优先队列,只有区间向单点建边只要out那颗树就行了

#include <bits/stdc++.h>
using namespace std; const int N = 1e5 + 10; vector<int> G[N << 2], ans;
int deg[N << 2], pos[N], id[N << 2], a[N], n; void add(int x, int y) {
G[x].push_back(y);
++deg[y];
} void build(int rt, int l, int r) {
id[rt] = -1;
if(l == r) {
pos[l] = rt;
id[rt] = l;
return;
}
int mid = l + r >> 1;
add(rt << 1, rt);
add(rt << 1 | 1, rt);
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
} void Add(int rt, int l, int r, int L, int R, int pnt) {
if(L <= l && r <= R) {
add(rt, pos[pnt]);
return;
}
int mid = l + r >> 1;
if(L <= mid)
Add(rt << 1, l, mid, L, R, pnt);
if(mid < R)
Add(rt << 1 | 1, mid + 1, r, L, R, pnt);
} void topo() {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
for(int i = 0; i < n; ++i)
if(!deg[pos[i]])
pq.push(make_pair(a[i], pos[i]));
while(!pq.empty()) {
pair<int, int> u = pq.top();
pq.pop();
if(u.first != -1)
ans.push_back(u.first);
for(auto &it: G[u.second])
if(--deg[it] == 0)
pq.push(make_pair(~id[it] ? a[id[it]] : -1, it));
}
for(int i = 0; i < ans.size(); ++i) {
printf("%d%c", ans[i], " \n"[i == ans.size() - 1]);
}
} int main() {
scanf("%d", &n);
build(1, 0, n - 1);
for(int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
int tmp = a[i] % n;
if(tmp == i) continue;
if(tmp < i)
Add(1, 0, n - 1, tmp, i - 1, i);
else {
Add(1, 0, n - 1, tmp, n - 1, i);
if(i)
Add(1, 0, n - 1, 0, i - 1, i);
}
}
topo();
return 0;
}

线段树优化建图(cf787d, 2019Wannafly Winter Camp Day7 Div1 E)的更多相关文章

  1. BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan

    Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...

  2. 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流

    [BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...

  3. 【ARC069F】Flags 2-sat+线段树优化建图+二分

    Description ​ 数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input ​ 第一行一个整数 N. ​ 接下来 N 行每行两个整数 xi, ...

  4. 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序

    题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足:  Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆.  现在 ...

  5. 【bzoj4699】树上的最短路(树剖+线段树优化建图)

    题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...

  6. 【BZOJ4276】[ONTAK2015]Bajtman i Okrągły Robin 线段树优化建图+费用流

    [BZOJ4276][ONTAK2015]Bajtman i Okrągły Robin Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2 ...

  7. 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra

    题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...

  8. 【bzoj4383】[POI2015]Pustynia 线段树优化建图+差分约束系统+拓扑排序

    题目描述 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r,k以及接下来k个正整数,表示a[l],a[l+1],...,a[r- ...

  9. BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流

    BZOJ_4276_[ONTAK2015]Bajtman i Okrągły Robin_线段树优化建图+最大费用最大流 Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1 ...

随机推荐

  1. linux实现php定时执行cron任务详解(转)

    对于PHP本身并没有一套解决方案来执行定时任务,不过是借助sleep函数完成的.这种方就是要提前做一些配置,如实现过程: 复制代码 代码如下: ignore_user_abort();//关掉浏览器, ...

  2. hdu 2842(矩阵高速幂+递推)

    题意:一个中国环的游戏,规则是一个木棒上有n个环.第一个环是能够任意放上或拆下的,剩下的环x假设想放上或拆下必须前一个环x-1是放上的且前x-2个环所有是拆下的,问n个环最少多少次操作能够所有拆掉. ...

  3. kubernetes容器探针检测

    系列目录 kubernetes提供了livenessProbe(可用性探针)和readinessProbe(就绪性探针)对容器的健康性进行检测,当然这仅仅简单的关于可用性方面的探测,实际上我们不仅仅要 ...

  4. js event 的target 和currentTarget

    target  点击的实际tag currentTarget 绑定事件的target

  5. VMware Workstation 14创建mac-10.12虚拟机详细步骤

     一.VMware和unlocker的下载和安装 链接:https://pan.baidu.com/s/15Z4DqRENt6JdyfJef_VWSw 密码:40vw 1.安装VMware Works ...

  6. StringUtils类使用 (转载)

    检查字符串是否为空或null或仅仅包含空格  String test = "";  String test1=" ";  String test2 = &quo ...

  7. Linux 操作系统中的进程结构

    前言 在 Linux 中,一个正在执行的程序往往由各种各样的进程组成,这些进程除了父子关系,还有其他的关系.依赖于这些关系,所有进程构成一个整体,给用户提供完整的服务( 考虑到了终端,即与用户的交互 ...

  8. C#用Infragistics 导入导出Excel

    最近项目中有数据的导入导出Excel的需求,这里做简单整理. 公司用的是Infragistics的产品,付费,不需要本地安装Office. 有需要的朋友可以下载 Infragistics.2013.2 ...

  9. 如何获取ipa 包的图片

    突然想起当初刚学习iOS的时候,就经常通过抓包和提取素材的方式来模仿App,今天就教大家如何一步步提取App的素材! 大家是否有过想要获取别人的素材的想法?看到某些App的资源很不错,很想导出来用用, ...

  10. iOS设备控制打印机输出文本

    本文转载至 http://tec.5lulu.com/detail/108krn1e6e66m8sbd.html 让我们来看看是如何实现的吧,首先要知道打印机的ip地址,然后用socket通过打印机的 ...