CodeForces - 786B -- 线段树优化建图

刚开始想了两个小时,打算把区间分块然后计算,但是这就很灵性了看了一个大佬的博客,侵删

#include<cstring>
#include<iostream>
#include<vector>
#include<cstdio>
#include<queue>
#define maxn 302020

using namespace std;
typedef long long ll;
const ll INF = 10000000000000;
int root1 = 0;
int root2 = 0;
struct Node {
	int p;
	ll len;
	Node(int a, ll b) :p(a), len(b) {}
};
vector<Node>G[maxn];
void insert(int be, int en, ll len) {
	G[be].push_back(Node(en, len));
}

ll dis[maxn];
int vis[maxn];
int num;
int lc[maxn];
int rc[maxn];

int bult1(int &node, int be, int en) {
	if (be == en) {
		node = be;
		return 0;
	}
	node = ++num;
	int mid = (be + en) / 2;
	bult1(lc[node], be, mid);
	bult1(rc[node], mid + 1, en);
	insert(node, lc[node], 0);
	insert(node, rc[node], 0);
	return 0;
}

int bult2(int &node, int be, int en) {
	if (be == en) {
		node = be;
		return 0;
	}
	node = ++num;
	int mid = (be + en) / 2;
	bult2(lc[node], be, mid);
	bult2(rc[node], mid + 1, en);

	insert(lc[node], node, 0);
	insert(rc[node], node, 0);
	return 0;
}
int n, m, s;
ll length;
int LL, RR;
int querry(int node, int be, int en, int op,int begin) {
	if (LL <= be && en <= RR) {
		
		if (op == 2) insert(begin, node, length);
		if (op == 3) insert(node, begin, length);
		return 0;
	}
	int mid = (be + en) / 2;
	if (LL <= mid) querry(lc[node], be, mid, op, begin);
	if (mid < RR) querry(rc[node], mid + 1, en, op, begin);
	return 0;
}
int dijstra(int be) {
	for (int i = 0; i < maxn -100; i++) {
		vis[i] = 0;
		dis[i] = INF;
	}
	queue<int>que;
	que.push(be);
	dis[be] = 0;
	while (!que.empty()) {
		int x = que.front();
		que.pop();
		vis[x] = 0;
		for (int i = 0; i < G[x].size(); i++) {
			int p = G[x][i].p;
			if (dis[p] > dis[x] + G[x][i].len) {
				dis[p] = dis[x] + G[x][i].len;
				if (!vis[p]) {
					vis[p] = 1;
					que.push(p);
				}
				
			}
		}
	}
	return 0;
}
int main() {
	int t;
	scanf("%d %d %d", &n, &m, &s);
	num = n+1;
	bult1(root1, 1, n);
	bult2(root2, 1, n);
	int be, en;

	for (int i = 0; i < m; i++) {
		scanf("%d", &t);
		if (t == 1) {
			scanf("%d %d %lld", &be, &en, &length);
			insert(be, en, length);
		}
		else {
			scanf("%d %d %d %lld", &be, &LL, &RR,&length);
			if (t == 2) querry(root1, 1, n, t, be);
			else  querry(root2, 1, n, t, be);
		}
	}
	dijstra(s);
	for (int i = 1; i <= n; i++) {
		if (dis[i] == INF) printf("-1 ");
		else printf("%lld ", dis[i]);
	}
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/lesning/p/11748601.html
今日推荐