首页 > 其他分享 >数据结构优化建图

数据结构优化建图

时间:2023-02-19 17:13:40浏览次数:49  
标签:cnt now int root 线段 add 建图 数据结构 优化

线段树优化建图

解决的是这样的一类问题:区间对区间连边,在这类图上做一些事情。(先假设是最短路,这个性质好一些)

区间问题会想到线段树。可以想到用线段树建立的虚点做这件事。具体怎么办呢?

image

image

底下两排叶子其实是一样的。也可以缩成一排。看怎么使用。两排的好处也有,点权可以放到上去的边上。

image

这样做了之后,每一次建边只需要增加一个点和 \(\log\) 条边。

总共 \(4n + T\) 个点,\(T \log n\) 条边。

考虑扩展到二维。

image

线段树套线段树优化建图。

总共 \(n \log n + T\) 个点,\(T \log n\) 条边。

这样建出来的树其实连通性方面看和原树一样。

模板题:https://codeforces.com/contest/1775/problem/F


#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e18;
//#define cerr if(false)cerr
//#define freopen if(false)freopen
#define watch(x) cerr  << (#x) << ' '<<'i'<<'s'<<' ' << x << endl
void pofe(int number, int bitnum) {
    string s; f(i, 0, bitnum) {s += char(number & 1) + '0'; number >>= 1; } 
    reverse(s.begin(), s.end()); cerr << s << endl; 
    return;
}
void cmax(int &x, int y) {if(x < y) x = y;}
void cmin(int &x, int y) {if(x > y) x = y;}
//调不出来给我对拍!
int cnt;
int root[2];
int lc[1000010], rc[1000010];
vector<pii> g[1000010];
int build(int l, int r, int t) {
    if(l == r) {return l;}
    int now = ++cnt;
    int mid=(l+r)>>1; 
    lc[now] = build(l, mid, t); 
    rc[now] = build(mid + 1, r, t);
    if(t == 0) {
        g[lc[now]].push_back({now,0}); g[rc[now]].push_back({now,0});
    }
    else {
        g[now].push_back({lc[now],0}); g[now].push_back({rc[now],0});
    }
    return now;
}
void add(int now, int l, int r, int x, int y, int c, int w, int t) {
    if(l >= x && r <= y) {
        if(t == 0) {g[now].push_back({c,w});}
        else {g[c].push_back({now,0});}
        return;
    }
    if(l > y || r < x) return;
    int mid=(l+r)>>1;
    add(lc[now], l, mid, x, y, c, w, t); add(rc[now], mid + 1, r, x, y, c, w, t);
}
int dis[1000010];
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
    //freopen();
    //freopen();
    //time_t start = clock();
    //think twice,code once.
    //think once,debug forever.
    int n, q, s; cin >> n >> q >> s; cnt = n; 
    root[0] = build(1,n,0); root[1] = build(1,n,1);
 //   cout << root[0] << " " << root[1] << endl;
    f(i, 1, q) {
        int op; cin >> op;
        if(op == 1) {
            int v, u, w; cin >> v >> u >> w; 
            add(root[0], 1, n, v, v, ++cnt, w, 0); 
            add(root[1], 1, n, u, u, cnt, w, 1);
        }
        else if(op == 2) {
            int v, l, r, w; cin >> v >> l >> r >> w;
            add(root[0], 1, n, v, v, ++cnt, w, 0);
            add(root[1], 1, n, l, r, cnt, w, 1);
        }
        else {
            int v, l, r, w; cin >> v >> l >> r >> w;
            add(root[0], 1, n, l, r, ++cnt, w, 0);
            add(root[1], 1, n, v, v, cnt, w, 1);
        }
    }
   // f(i, 1, cnt) {cout << i << ":" << endl; for(pii j : g[i]) {cout << j.first << " " << j.second << endl;}}
    priority_queue<pii> que; f(i, 1, cnt) dis[i] = inf; que.push({0, s});
    while(!que.empty()) {
        pii nc = que.top(); int now = nc.second, cost = -nc.first; que.pop(); 
        if(dis[now] <= cost) continue; 
        dis[now] = cost;
        for(pii i : g[now]) {
            if(dis[i.first] > dis[now] + i.second) {
                que.push({-dis[now] - i.second, i.first});
            }
        }
    }
    f(i, 1, n) cout << (dis[i] == inf ? -1 : dis[i]) << " ";
    cout << endl;
    //time_t finish = clock();
    //cout << "time used:" << (finish-start) * 1.0 / CLOCKS_PER_SEC <<"s"<< endl;
    return 0;
}
/*
2023/x/xx
start thinking at 10:05

线段树建实点,两棵,cnt



start coding at 
finish debugging at h:mm
*/

前缀优化建图

如果允许弱化版的功能,比如对 \([l,r]\) 以外的点连边,也就相当于前缀后缀连边,那么可以用树状数组的结构简化。

建 \(n\) 个虚点,表示 \(1 \sim n\) 的前缀。建边过程中不需要再建立虚点。只需要连边。

image

一共 \(2 n\) 个点,\(2n + m\) 条边。

应用

最短路:可以求出到区间的最短路。显然是和原图一样的。
拓扑序:可以建立一个包含实点和虚点的拓扑序(实点的拓扑序可以应用)

image

拓扑序的最后一个位置一定是第一棵线段树的根,第一个位置一定是第二棵线段树的根。

如果原图上没有环,那么新图上也不会出现环。

最小生成树:和点有关系,没有那么好搞。

强连通分量:可以在新图上缩点做强连通分量。

标签:cnt,now,int,root,线段,add,建图,数据结构,优化
From: https://www.cnblogs.com/Zeardoe/p/17135081.html

相关文章

  • Golang数据结构
    数据类型不同类型的内存样式图查看变量类型使用fmt.Printfpackagemainimport"fmt"funcmain(){str:="Helloworld"fmt.Printf("%T",str)}使用re......
  • [数据结构] 稀疏矩阵的转置与快速转置
    稀疏矩阵稀疏矩阵的定义在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵。假设在m*n的矩阵中,有t个非0元......
  • 【数据结构】八种常见数据结构介绍
    数据结构是计算机存储、组织数据的方式。一种好的数据结构可以带来更高的运行或者存储效率。数据在内存中是呈线性排列的,但是我们可以使用指针等道具,构造出类似“树形”的......
  • 前端性能优化之gzip
    前言HTTP可以对传输的内容进行压缩,减少网络实际传输数据的大小。服务器会将资源进行压缩后传输到客户端,浏览器收到文件后进行解析。对于纯文本文件可以压缩到之前大小的30%......
  • Hibernate 性能优化_1
    大概如此:不一定说在每个项目中都合适 1、比如,开了N多文件而没关,比如开了地址池而没清,比如分页读了N多页而没有清内存 2、对于ManyToOne,如果设为FetchType=Eager,则会产生1+......
  • Hibernate 性能优化_3
    二级缓存 对于二级缓存,其实并不一定要在项目中使用除非是对项目要求非常高的情况下使用 如果要用,应使用在:经常被访问,改动不大,数量不多,比如权限,比如组织机构 load()默认使......
  • Hibernate 性能优化_2
    createQuery("FROM****").list()和createQuery("FROM****").iterate()的区别 1、list()时,会取出所有的数据,Iterate()时,只取所有记录的主键,当用到哪条时,再根据id去取哪条......
  • SQL性能优化的47个小技巧,你了解多少?
    大家好,我是哪吒。1、先了解MySQL的执行过程了解了MySQL的执行过程,我们才知道如何进行sql优化。客户端发送一条查询语句到服务器;服务器先查询缓存,如果命中缓存,则立即返......
  • 面试官:React怎么做性能优化
    前言最近一直在学习关于React方面的知识,并有幸正好得到一个机会将其用在了实际的项目中。所以我打算以博客的形式,将我在学习和开发(React)过程中遇到的问题记录下来。这两......
  • MySQL优化:MRR Multi-Range Read多范围读取
    在优化MySQL查询的时候,在explain中看到了  详细解释:MySQL中的MRR指的是Multi-RangeRead,即多范围读取。在MySQL5.6及更高版本中,当使用InnoDB存储引擎时,MRR是一种优......