线段树优化建图(cf787d, 2019Wannafly Winter Camp Day7 Div1 E)
线段树优化建图,用于区间到区间建边时降低空间复杂度
建立两颗线段树,一颗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)的更多相关文章
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
		Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ... 
- 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流
		[BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ... 
- 【ARC069F】Flags 2-sat+线段树优化建图+二分
		Description  数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input  第一行一个整数 N.  接下来 N 行每行两个整数 xi, ... 
- 【bzoj5017】[Snoi2017]炸弹  线段树优化建图+Tarjan+拓扑排序
		题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆. 现在 ... 
- 【bzoj4699】树上的最短路(树剖+线段树优化建图)
		题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ... 
- 【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 ... 
- 【bzoj3073】[Pa2011]Journeys  线段树优化建图+堆优化Dijkstra
		题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ... 
- 【bzoj4383】[POI2015]Pustynia  线段树优化建图+差分约束系统+拓扑排序
		题目描述 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息,每条信息包含三个数l,r,k以及接下来k个正整数,表示a[l],a[l+1],...,a[r- ... 
- 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 ... 
随机推荐
- selenium之 文件上传方法
			文件上传是所有UI自动化测试都要面对的一个头疼问题 首先,我们要区分出上传按钮的种类,大体上可以分为两种,一种是input框,另外一种就比较复杂,通过js.flash等实现,标签非input 我们分别 ... 
- cocos2d-x项目101次相遇:在HelloWorld上--建立新场景
			cocos2d-x 101次相遇 / 文件夹 1 安装和环境搭建 -xcode 2 Scenes , Director, Layers, Sprites 3 建立图片菜单 4 在 ... 
- scp windows 和 linux 远程复制 (双向)
			一下命令在cmd中 从w -> l : scp D:\a.txt root@192.168.2.113:/home/a 从l -> w: scp root@192.168.2.113:/h ... 
- MySQL windows集群(转)
			http://blog.csdn.net/zhangking/article/details/5670070 MySQL 群集是 MySQL 适合于分布式计算环境的高可用.高冗余版本.它采用了 ... 
- kubernetes对象之secrets
			系列目录 Secrets是Kubernetes中一种对象类型,用来保存密码.私钥.口令等敏感信息.与直接将敏感信息嵌入image.pod相比,Secrets更安全.更灵活,用户对敏感信息的控制力更强. ... 
- JavaSE 文件递归之删除&获取文件夹文件夹中全部的以.jpg的文件的绝对路径
			1.递归删除文件 假设一个文件夹以下还有子文件夹,进行删除的话会 报错,这个时候要使用递归的方式来删除这个文件文件夹中的全部文件以及文件夹 package cn.itcast.digui; impor ... 
- LeetCode(88)题解-- Merge Sorted Array
			https://leetcode.com/problems/merge-sorted-array/ 题目: Given two sorted integer arrays nums1 and nums ... 
- [工具]利用EasyRTSPClient工具检查摄像机RTSP流不能播放原因以及排查音视频数据无法播放问题
			出现问题 我们在做流媒体开发的过程中,进程会出现摄像机RTSP流莫名其妙无法播放的问题,而我们常用的vlc经常是直接弹出一个无法播放的提示框就完事了,没有说明出错的原因,或者在vlc的消息里面能看到日 ... 
- EasyPusher手机直播编码推送之图像旋转90度后画面重复的问题
			本文转自EasyDarwin开源团队开发Holo的博客:http://blog.csdn.net/holo_easydarwin 最初在做EasyPusher手机直播的时候遇到过一个问题:手机竖屏推送 ... 
- EasyDarwin开源流媒体云平台中boost Base64编解码后与源长度不匹配的bug
			本文转自EasyDarwin团队Alex的博客:http://blog.csdn.net/cai6811376 EasyDarwin云平台中部分协议使用了Base64编码昨晚报文通信的载体.比如在对摄 ... 
