zoukankan      html  css  js  c++  java
  • Codeforces 786B Legacy(线段树优化建图)

    题目链接  Legacy

    首先对于输入的$n$,建立一棵线段树。

    显然线段树有大概$2n$个结点,每个节点对应一段区间

    我们把这$2n$个结点加入我们的无向图中,一起跑最短路。

    具体连边方案:

    我们把这棵线段树复制一下,另外一棵倒过来。

    首先第一棵线段树,每个结点向他的两个儿子连有向边,连到叶子结点的时候

    叶子结点向原来的$n$个点连边

    也就是说$[l, l]$向原来编号为$l$的这个点连边。

    然后$1$到$n$这$n$个点分别向第二棵线段树的叶子结点分别连有向边

    具体一点,$l$号点向$[l', l']$连边。

    然后在第二棵线段树中,两个儿子向父亲连边,依次类推。

    接着就是对给定的输入进行连边操作了。

    对于点连向点的,普通操作就行了。

    对于点连向区间的,把点连向第一棵线段树的结点。大概要连$logn$条边

    对于区间连向点的,把第二棵线段树的结点连向这个点。大概也连$logn$条边

    然后跑一边堆优化Dij就可以了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define	ls		(i << 1)
    #define	rs		(i << 1 | 1)
    #define	mid		((L + R) >> 1)
    #define	lson		ls, L, mid
    #define	rson		rs, mid + 1, R
    
    
    typedef long long LL;
    typedef pair <int, int> PII;
    
    const int N = 2e6 + 10;
    
    struct node{
    	int u;
    	LL w;
    	friend bool operator < (const node &a, const node &b){
    		return a.w > b.w;
    	}
    };
    
    map <PII, int> mp;
    int tot = 0;
    int n, q, s, cnt;
    LL dis[N];
    vector <node> v[N];
    
    void addedge(int x, int y, LL z){
    	v[x].push_back({y, z});
    }
    
    void build(int i, int L, int R){
    	cnt = max(cnt, i);
    	if (L == R){
    		addedge(i + n, L, 0);
    		return;
    	}
    
    	build(lson);
    	build(rson);
    	addedge(i + n, ls + n, 0);
    	addedge(i + n, rs + n, 0);	
    }
    
    void build2(int i, int L, int R){
    	if (L == R){
    		addedge(L, i + n + cnt, 0);
    		return;
    	}
    
    	build2(lson);
    	build2(rson);
    	addedge(ls + n + cnt, i + n + cnt, 0);
    	addedge(rs + n + cnt, i + n + cnt, 0);
    }
    
    
    void work1(int i, int L, int R, int l, int r, int u, LL val){
    	if (l <= L && R <= r){
    		addedge(u, i + n, val);
    		return;
    	}
    
    	if (l <= mid) work1(lson, l, r, u, val);
    	if (r >  mid) work1(rson, l, r, u, val);
    }
    
    void work2(int i, int L, int R, int l, int r, int u, LL val){
    	if (l <= L && R <= r){
    		addedge(i + n + cnt, u, val);
    		return;
    	}
    
    	if (l <= mid) work2(lson, l, r, u, val);
    	if (r >  mid) work2(rson, l, r, u, val);
    }
    
    void dij(int s, LL dis[], vector <node> v[]){
    	priority_queue <node> q;
    	static bool vis[N];
    	rep(i, 1, 2e6) dis[i] = 1e18, vis[i] = false;
    	q.push({s, 0});
    	dis[s] = 0;
    	while (!q.empty()){
    		int u = q.top().u; q.pop();
    		if (vis[u]) continue;
    		vis[u] = 1;
    		for (auto edge : v[u]) if (dis[u] + edge.w < dis[edge.u]){
    			dis[edge.u] = dis[u] + edge.w;
    			q.push({edge.u, dis[edge.u]});
    		}
    	}
    }
    
    int main(){
    
    	scanf("%d%d%d", &n, &q, &s);
    	tot = n;
    	build(1, 1, n);
    	build2(1, 1, n);
    
    	while (q--){
    		int op;
    		scanf("%d", &op);
    		if (op == 1){
    			int x, y;
    			LL z;
    			scanf("%d%d%lld", &x, &y, &z);
    			if (x == y) continue;
    			addedge(x, y, z);
    		}
    		else if (op == 2){
    			int u, l, r;
    			LL z;
    			scanf("%d%d%d%lld", &u, &l, &r, &z);
    			work1(1, 1, n, l, r, u, z);
    		}
    
    		else{
    			int u, l, r;
    			LL z;
    			scanf("%d%d%d%lld", &u, &l, &r, &z);
    			work2(1, 1, n, l, r, u, z);
    		}
    	}
    
    	dij(s, dis, v);
    	rep(i, 1, n) printf("%lld
    ", (dis[i] < 1e18 ? dis[i] : -1));
    	return 0;
    }
    
  • 相关阅读:
    利用jquery获取html中被选中的input的值
    获取表单选中的值(利用php和js两种方式)
    复习
    Ajax请求中的async:false/true的作用
    Jquery
    C#创建控制台项目引用Topshelf的方式,部署windows服务。
    你循环的时候就可以给他们赋值了,那么就不用addClass,再根据类选择器处理,代码能一气呵成就别写成两段了
    SQL server 数据库中插入中文变???格式乱码的问题另一种容易忽略的情况(C#操作dapper)
    SQL 两个表有关联,通过其中一个表的列,更新另一个表的列。
    SQL server 存储过程中 列传行
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7953759.html
Copyright © 2011-2022 走看看