首页 > 其他分享 >这就是我们的李超线段树啊,你们有没有这样的李超线段树啊?

这就是我们的李超线段树啊,你们有没有这样的李超线段树啊?

时间:2024-02-24 10:14:29浏览次数:30  
标签:y2 有没有 int 线段 李超 y1 x2 x1

沟槽的公式,真是公公又式式啊。

考虑一个线段树节点维护一个线段(但一条线段可以被多个线段树节点维护),需要保证该节点被线段完全覆盖。

每次添加一个线段的时候:

  1. 如果当前节点没有被这个线段完全覆盖,那么直接递归左右儿子修改。

  2. 如果当前节点的线段比新线段严格劣(也就是对于每一个 \(x\) 都有 \(y_{old}<y_{new}\) 或者 \(y_{old}=y_{new}\) 且编号比新线段大),则这条线段在该节点维护的区间上不再可能成为答案,直接用新线段替换掉。

  3. 同理,如果新线段严格劣,则直接停止递归,新线段在这个节点上不再可能成为答案。

  4. 如果新老线段有交点,设其交点的 \(x\) 轴为 \(p\),若 \(p\le mid\),则说明在右半区间,一定有一个线段比另一个完全优,则直接把当前的节点维护的线段改为这个完全优的线段,将那个劣的线段下放到 \([l,mid]\) 修改。\(p>mid\) 同理。

然后发现这玩意,如果你有交点,那么你必定把递归的区间缩小了一半,所以你最多递归 \(\log n\) 次,然后由于每个线段在线段树上可以被 \(\log n\) 个区间表示,所以每次修改的复杂度是 \(O(\log ^2n)\) 的,注意这里的 \(n\) 指的是线段树的大小。

对于询问位置 \(x\),答案是在线段树上维护 \([x,x]\)​ 这个区间的节点与其所有祖先的答案最大值。

所以最终复杂度 \(O(q\log^2 n)\),其中 \(q\) 是修改次数。

const int MAXN = 1e6 + 5, N = 39989, mxn = 4e5 + 5;
int n;

struct _node {
	int x1, y1, x2, y2, id;
	// ensure that x1 <= x2
} tr[MAXN << 2];

double getVal(_node x, int pos) {
	if (pos < x.x1 || pos > x.x2) return 0;
	if (x.x1 == x.x2) return max(x.y1, x.y2);
	const auto k = (x.y2 - x.y1) * 1.0 / (x.x2 - x.x1);
	return (pos - x.x1) * 1.0 * k + x.y1;
}

void insert(int p, int l, int r, _node v) {
	if (v.x1 <= l && r <= v.x2) {
		const auto vl1 = getVal(tr[p], l), vr1 = getVal(tr[p], r);
		const auto vl2 = getVal(v, l), vr2 = getVal(v, r);
		if (vl1 < vl2 && vr1 < vr2) return tr[p] = v, void();
		if (vl1 == vl2 && vr1 == vr2 && tr[p].id > v.id) return tr[p] = v, void();
		if (vl2 < vl1 && vr2 < vr1) return;
		if (vl1 == vl2 && vr1 == vr2 && tr[p].id < v.id) return;
		const auto vm1 = getVal(tr[p], mid), vm2 = getVal(v, mid);
		if (vl1 <= vl2) {
			if (vm1 <= vm2) insert(rson, mid + 1, r, tr[p]), tr[p] = v;
			else insert(lson, l, mid, v);
		}
		else {
			if (vm1 <= vm2) insert(lson, l, mid, tr[p]), tr[p] = v;
			else insert(rson, mid + 1, r, v);
		}
		return;
	}
	if (v.x1 <= mid) insert(lson, l, mid, v);
	if (mid < v.x2) insert(rson, mid + 1, r, v);
}

pair<double, int> mx(pair<double, int> a, pair<double, int> b) {
	if (a.first == b.first) return a.second < b.second ? a : b;
	return a.first > b.first ? a : b;
}

pair<double, int> query(int p, int l, int r, int pos) {
	if (l == r) return make_pair(getVal(tr[p], pos), tr[p].id);
	if (pos <= mid) return mx(make_pair(getVal(tr[p], pos), tr[p].id), query(lson, l, mid, pos));
	else return mx(make_pair(getVal(tr[p], pos), tr[p].id), query(rson, mid + 1, r, pos));
}

int lastAns, id;

void work() {
	cin >> n;
	while (n--) {
		int opt, k, x1, y1, x2, y2;
		cin >> opt;
		if (opt == 0) {
			cin >> k;
			k = (k + lastAns - 1 + N) % N + 1;  
			const auto ans = query(1, 1, mxn, k);
			cout << (lastAns = ans.second) << endl;
		}
		if (opt == 1) {
			cin >> x1 >> y1 >> x2 >> y2;
			x1 = (x1 + lastAns - 1 + N) % N + 1;
			x2 = (x2 + lastAns - 1 + N) % N + 1;
			y1 = (y1 + lastAns - 1 + (int)1e9) % (int)(1e9) + 1;
			y2 = (y2 + lastAns - 1 + (int)1e9) % (int)(1e9) + 1;
			if (x1 > x2) swap(x1, x2), swap(y1, y2);
			insert(1, 1, mxn, {x1, y1, x2, y2, ++id});
		}
	}
}

标签:y2,有没有,int,线段,李超,y1,x2,x1
From: https://www.cnblogs.com/XiaoQuQu/p/18030797

相关文章

  • 线段树分治&cdq分治&整体二分
    preface感觉三种分治算法容易搞混并不容易区分它们使用的场景和题目(虽然有些题目根据性质可以使用多种分治),所以还是要归纳一下线段树分治Part1主要是处理一类带有撤回的问题,也就是一次修改只对一段区间生效(这里的区间指的是时间)即区间修改,单点查询流程大致是把区间修改挂在......
  • 线段树乱搞大法
    线段树乱搞大法Part1普通线段树简单的区间或单点问题,支持四则运算(可以扩展成可合并的信息,如hash)权值线段树每个节点维护值域为\([l,r]\)的个数,可以维护全局第k大(线段树二分),zkw线段树...Part2懒标记区间操作,历史版本最值/和标记永久化区间操作,单点修改要求:操作顺序不......
  • UOJ228/HDU5828 基础数据结构练习题/Rikka with Sequence 题解(势能线段树)
    势能线段树。如果线段树上一个节点的\(\max-\min\ge2\),我们称其为关键节点,考虑定义势能\(\phi\)为线段树上关键节点的个数。对于每次开方操作,如果当前节点为关键节点,则暴力递归左右儿子修改,否则:如果当前节点\(\max=\min\)或\(\max=\min+1\)且\(\max\)不是完全平方数,......
  • 山海经(线段树)题解
    原题链接:COGS775题目描述:“南山之首曰鹊山。其首曰招摇之山,临于西海之上,多桂,多金玉。有草焉,其状如韭而青华,其名曰祝余,食之不饥……又东三百里,曰堂庭之山,多棪木,多白猿,多水玉,多黄金。又东三百八十里,曰猨翼之山,其中多怪兽,水多怪鱼,多白玉,多蝮虫,多怪蛇,名怪木,不可以上。……”(其实就......
  • 线段树模板
    向上回溯voidpushup(intrt){ t[rt].sum+=t[lc].sum+t[rc].sum; t[rt].mx=max(t[lc].mx,t[rc].mx);}建树voidbuild(intrt,intl,intr){ t[rt].l=l; t[rt].r=r; if(l==r){ t[rt].mx=t[rt].sum=a[l]; return; } intmid=(l+r)>>1......
  • 洛谷题单指南-贪心-P1803 凌乱的yyy / 线段覆盖
    原题链接:https://www.luogu.com.cn/problem/P1803题意解读:通过某种贪心策略,使得能参加的比赛数越多越好。解题思路:将比赛按照结束时间由小到大哦排序,贪心策略是优先选择结束时间早的比赛,因为这样能保证后面参加更多其他比赛100分代码:#include<bits/stdc++.h>usingnamespa......
  • 山海经&&Atcoder Alternating String (线段树)
    前言:为什么把他们放在一起?因为我发现把pushup向上回溯放结构体类型函数里比较方便并且这两题确实也有相同思想山海经这题分三种情况左子树前缀和+右子树前缀和2.右子树后缀和与右总区间+左子树3.左区间最大子段与右区间最大子段与左后缀与右前缀特别要注意......
  • 2.21闲话 & solution『 有没有/谁/能够代替我』
    上午有唐氏模拟赛,100/0/0/20,rk7/15,鉴定为最唐的一次T1签到题,思路很简单题面ame是一个可爱的女孩子,她想要你帮她排序。给定\(4\timesn\)个数,要求将其分为\(n\)组,使得对于每组四个数,所有组中的\(|a\timesb-c\timesd|\)和最大,求最大和。排序,对于前\(2n\)大的,尽量把大......
  • 线段树学习笔记
    目录线段树的基础知识什么是线段树线段树的基本操作线段树的建树线段树的单点修改线段树的区间查询线段树的区间修改模板动态开点一些例题TheChildandSequence解法分析CodeLegacy相关知识:线段树优化建图解法分析Code线段树的基础知识什么是线段树线段树是一种分治思想的二叉......
  • 小清新线段树
    小清新线段树定义结合时间复杂度分析(势能分析)以及懒标记应用的非传统线段树可以理解为带剪枝的线段树复杂度证明以TheChildandSequence为例,先看操作1,2,对于一个数\(x\)进行取模,要么这个数保持不变。若模数\(M>\frac{x}{2}\),则剩余部分小于\(\frac{x}{2}\);若模数\(......