线段树进阶应用学习笔记(一):线段树优化建图、特殊的线段树

线段树优化建图

算法流程

复杂度分析

例题

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5e5, M = 5e6 + 9;
struct Edge{
	int v, w, nex;
} e[M];
int head[M], ecnt;
void AddEdge(int u, int v, int w){
	e[++ecnt] = Edge{v, w, head[u]};
	head[u] = ecnt;
}
int t[M], n, q, s;
void build(int id, int L, int R){
	if(L == R){
		t[L] = id;
		AddEdge(id, id + N, 0);
		AddEdge(id + N, id, 0);
		return;
	}
	int mid = (L + R) >> 1;
	AddEdge(id, id << 1, 0);
	AddEdge(id, id << 1 | 1, 0);
	AddEdge((id << 1) + N, id + N, 0);
	AddEdge((id << 1 | 1) + N, id + N, 0);
	build(id << 1, L, mid);
	build(id << 1 | 1, mid + 1, R);
}
void connect(int u, int id, int L, int R, int qL, int qR, int qx, int type){
	if(L == qL && R == qR){
		if(type == 2)
			AddEdge(u, id, qx);
		else
			AddEdge(id + N, u, qx);
		return;
	}
	int mid = (L + R) >> 1;
	if(qR <= mid)
		connect(u, id << 1, L, mid, qL, qR, qx, type);
	else if(qL > mid)
		connect(u, id << 1 | 1, mid + 1, R, qL, qR, qx, type);
	else {
		connect(u, id << 1, L, mid, qL, mid, qx, type);
		connect(u, id << 1 | 1, mid + 1, R, mid + 1, qR, qx, type);
	}
}
int dis[M];
queue <int> qu;
bool inq[M];
void spfa(){
	memset(dis, 0x3f3f, sizeof(dis));
	dis[t[s]] = 0;
	qu.push(t[s]);
	inq[t[s]] = true;
	while(!qu.empty()){
		int u = qu.front();
		for(int i = head[u]; i; i = e[i].nex){
			int v = e[i].v;
			if(dis[v] > dis[u] + e[i].w){
				dis[v] = dis[u] + e[i].w;
				if(!inq[v]){
					qu.push(v);
					inq[v] = true;
				}
			}
		}
		qu.pop();
		inq[u] = false;
	}
}
signed main(){
	scanf("%lld%lld%lld", &n, &q, &s);
	build(1, 1, n);
	for(int i = 1; i <= q; i++){
		int opt, u, v, w, L, R;
		scanf("%lld%lld", &opt, &u);
		if(opt == 1){
			scanf("%lld%lld", &v, &w);
			AddEdge(t[u], t[v], w);
		} else {
			scanf("%lld%lld%lld", &L, &R, &w);
			connect(t[u], 1, 1, n, L, R, w, opt);
		}
	}
	spfa();
	for(int i = 1; i <= n; ++i)
		if(dis[t[i]] == 0x3f3f3f3f3f3f3f3f)
			printf("-1 ");
		else
			printf("%lld ", dis[t[i]]);
	return 0 ;
}

李超线段树

算法流程

复杂度分析

例题

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 9, MOD1 = 39989, MOD2 = 1e9;
const double eps = 1e-9;
struct Line{
    double k, b;
} l[N];
struct Comp{
	double res;
	int id;
};
int s[N << 1], lcnt;
int cmp(double x, double y){
    if(x - y > eps)
        return 1;
    else if(y - x > eps)
        return -1;
    else
        return 0;
}
double calc(int id, int x){
    return l[id].b + x * l[id].k;
}
void modify(int id, int L, int R, int u){
    int &v = s[id], mid = (L + R) >> 1;
    int flag = cmp(calc(u, mid), calc(v, mid));
    if(flag == 1 || (!flag && u < v))
        swap(u, v);
    int flagl = cmp(calc(u, L), calc(v, L)), flagr = cmp(calc(u, R), calc(v, R));
    if(flagl == 1 || (!flagl && u < v))
        modify(id << 1, L, mid, u);
    if(flagr == 1 || (!flagr && u < v))
        modify(id << 1 | 1, mid + 1, R, u);
}
void update(int id, int L, int R, int qL, int qR, int u){
    if(L == qL && R == qR){
        modify(id, L, R, u);
        return;
    }
    int mid = (L + R) >> 1;
    if(qR <= mid)
        update(id << 1, L, mid, qL, qR, u);
    else if(qL > mid)
        update(id << 1 | 1, mid + 1, R, qL, qR, u);
    else {
        update(id << 1, L, mid, qL, mid, u);
        update(id << 1 | 1, mid + 1, R, mid + 1, qR, u);
    }
}
Comp pmax(Comp x, Comp y) {
  if(cmp(x.res, y.res) == -1)
    return y;
  else if(cmp(x.res, y.res) == 1)
    return x;
  else
    return x.id < y.id ? x : y;
}

Comp query(int id, int L, int R, int k){
	if(R < k || k < L)
		return Comp{0, 0};
	int mid = (L + R) >> 1;
	double res = calc(s[id], k);
	if(L == R)
		return Comp{res, s[id]};
	return pmax(Comp{res, s[id]}, pmax(query(id << 1, L, mid, k), query(id << 1 | 1, mid + 1, R, k)));
}
int n, lastans;
int main(){
	scanf("%d", &n);
    while(n--){
        int op, k, x0, y0, x1, y1;
        scanf("%d", &op);
        if(op == 0){
            scanf("%d", &k);
            k = (k + lastans - 1 + MOD1) % MOD1 + 1;
            printf("%d\n", lastans = query(1, 1, MOD1, k).id);
        } else {
            scanf("%d%d%d%d", &x0, &y0, &x1, &y1);
            x0 = (x0 + lastans - 1 + MOD1) % MOD1 + 1;
            x1 = (x1 + lastans - 1 + MOD1) % MOD1 + 1;
            y0 = (y0 + lastans - 1 + MOD2) % MOD2 + 1;
            y1 = (y1 + lastans - 1 + MOD2) % MOD2 + 1;
            if(x0 > x1){
                swap(x0, x1);
                swap(y0, y1);
            }
            lcnt++;
		    if(x0 == x1){
		        l[lcnt].k = 0;
		        l[lcnt].b = max(y0, y1);
		    } else {
		        l[lcnt].k = (y1 - y0) * 1.0 / (x1 - x0);
		        l[lcnt].b = y0 - l[lcnt].k * x0;
		    }
            update(1, 1, MOD1, x0, x1, lcnt);
        }
    }
	return 0;
}

zkw 线段树

吉司机线段树

posted @   JPGOJCZX  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示