首页 > 编程语言 >算法学习笔记(18):珂朵莉树

算法学习笔记(18):珂朵莉树

时间:2024-05-13 08:57:17浏览次数:30  
标签:Node return int 18 odt 朵莉树 算法 split auto

珂朵莉树

这个名字我猜是来源于初次诞生这个算法的题目->Willem, Chtholly and Seniorious

算法

适用于数据随机, 并且有区间推平操作, 也就是区间赋值操作, 就可以用set维护, 达到优秀的 \(O(nlogn)\) 时间复杂度。

定义

struct Node{
	int l, r;
	mutable int v;
	Node(int l, int r = 0, int v = 0) : l(l), r(r), v(v) {}
	bool operator < (const Node &x) const {
		return l < x.l;
	}
};
set<Node> odt;

每个节点代表一个区间

split操作

就是把 \(x\) 所在区间分裂成 \([l, x - 1]\) 和 \([x, r]\)。

auto split(int x) {
	auto it = odt.lower_bound(Node(x));
	if (it != odt.end() && it->l == x) return it;
	--it;
	if (it->r < x) return odt.end();
	int l = it->l, r = it->r, v = it->v;
	odt.erase(it);
	odt.insert(Node(l, x - 1, v));
	return odt.insert(Node(x, r, v)).first;
} 

assign操作

就是把 \([l, r]\) 区间重构了, 需要先把 \(l\) 和 \(r + 1\) split一下, 才能刚好提出 \([l, r]\) 这个区间, 然后暴力把这之间的全部推平。

void assign(int l, int r, int v) {
	auto itr = split(r + 1), itl = split(l);
	odt.erase(itl, itr);
	odt.insert(Node(l, r, v));
}

例题

Willem, Chtholly and Seniorious

其他各种操作都直接暴力搞, 时间复杂度在数据随机的时候都很优秀。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
struct Node{
	int l, r;
	mutable int v;
	Node(int l, int r = 0, int v = 0) : l(l), r(r), v(v) {}
	bool operator < (const Node &x) const {
		return l < x.l;
	}
};
set<Node> odt;
int n, m, seed, vmax, a[N];
auto split(int x) {
	auto it = odt.lower_bound(Node(x));
	if (it != odt.end() && it->l == x) return it;
	--it;
	if (it->r < x) return odt.end();
	int l = it->l, r = it->r, v = it->v;
	odt.erase(it);
	odt.insert(Node(l, x - 1, v));
	return odt.insert(Node(x, r, v)).first;
} 
void assign(int l, int r, int v) {
	auto itr = split(r + 1), itl = split(l);
	odt.erase(itl, itr);
	odt.insert(Node(l, r, v));
}
void add(int l, int r, int v) {
	auto itr = split(r + 1), itl = split(l);
	for (auto it = itl; it != itr; ++it) 
		it->v += v;
}
struct Rk{
	int val, cnt;
	bool operator < (const Rk &x) const { return val < x.val; }
	Rk(int val, int cnt) : val(val), cnt(cnt) { }
};
int rk(int l, int r, int k) {
	auto itr = split(r + 1), itl = split(l);
	vector<Rk> q;
	for (auto it = itl; it != itr; ++it) 
		q.push_back(Rk(it->v, it->r - it->l + 1));
	sort(q.begin(), q.end());
	for (auto i : q) {
		if (i.cnt < k) k -= i.cnt;
		else return i.val;
	} 
}
int qpow(int a, int b, int p) {
	int res = 1;
	a %= p;
	for ( ; b; b >>= 1, a = a * a % p) if (b & 1) res = res * a % p;
	return res;
}
int calP(int l, int r, int x, int y) {
	auto itr = split(r + 1), itl = split(l);
	int res = 0;
	for (auto it = itl; it != itr; it++) 
		(res += qpow(it->v, x, y) * (it->r - it->l + 1) % y) %= y;
	return res;
}
int rnd() {
    int ret = seed;
    seed = (seed * 7 + 13) % mod;
    return ret;
}
signed main() {
	cin >> n >> m >> seed >> vmax;
    for (int i = 1; i <= n; ++i) {
        a[i] = (rnd() % vmax) + 1;
        odt.insert(Node(i, i, a[i]));
    }
    for (int i = 1; i <= m; ++i) {
        int op, l, r, x, y;
        op = (rnd() % 4) + 1;
        l = (rnd() % n) + 1;
        r = (rnd() % n) + 1;
        if (l > r) swap(l, r);
        if (op == 3) {
            x = (rnd() % (r - l + 1)) + 1;
        } else {
            x = (rnd() % vmax) + 1;
        }
        if (op == 4) {
            y = (rnd() % vmax) + 1;
        }
        if (op == 1) {
            add(l, r, x);
        } else if (op == 2) {
            assign(l, r, x);
        } else if (op == 3) {
            cout << rk(l, r, x) << endl;
        } else {	
            cout << calP(l, r, x, y) << endl;
        }
    }
	return 0;
}

标签:Node,return,int,18,odt,朵莉树,算法,split,auto
From: https://www.cnblogs.com/qerrj/p/18188572

相关文章

  • 跟着ChatGPT学算法-完全背包问题
    一、题目给定n个物品,第i个物品的重量为wgt[i-1]、价值为val[i-1],和一个容量为cap的背包。每个物品可以重复选取,问在限定背包容量下能放入物品的最大价值。 二、和ChatGPT聊聊您您是一位资深算法工程师,请深入浅出地给出完全背包问题的分析过程和完整带注释的Java代......
  • py面向算法
    近期想系统性的学习学习python,我想着了解一门语言是不是最开始就要会用他的一些基本语法来写题呢,抱着这个想法我就开始用c++写完一道题后用py再写一遍.但是py主要的一些语法还好,只是表现形式不同而已,但是py的输入输出和数组方面相对来说特殊不少,或者根本就没有数组这个概念,......
  • 策略梯度玩 cartpole 游戏,强化学习代替PID算法控制平衡杆
     cartpole游戏,车上顶着一个自由摆动的杆子,实现杆子的平衡,杆子每次倒向一端车就开始移动让杆子保持动态直立的状态,策略函数使用一个两层的简单神经网络,输入状态有4个,车位置,车速度,杆角度,杆速度,输出action为左移动或右移动,输入状态发现至少要给3个才能稳定一会儿,给2个完全学不明白,......
  • 记字符串匹配KMP算法
    字符串匹配是一类经典的问题,在字符串s中找出模式串t第一个元素的下标,如果没有匹配到,则返回-1。此问题在leetcode中甚至归类为简单。解决此问题最直接的思路是使用暴力解法,从第0个元素开始逐个比较元素,当字符不匹配时,s的指针向前移动一位,不断重复。这种思路最简单且直接,但是无法通......
  • 自定义各类基础排序算法
    接口函数基础信息/********************************************************************* 文件名称: 数据结构中对于无序数列的排序算法* 文件作者:[email protected]* 创建日期:2024/05/11* 文件功能:对无序数列进行排序* 注意事项:None** C......
  • 匈牙利算法模板(二分图)
    booldfs(intnow){for(inti=h[now];i;i=nxt[i]){intt=to[i];//这里不用考虑会有回到父结点的边的问题//因为每次都是从左部找邻接点if(!vis[t]){vis[t]=true;//如果邻接点t是非匹配点,则找到一条增广路,匹配......
  • 代码随想录算法训练营第四天 | 23.两l两交换链表中的节点 19.删除链表的倒数第N个节点
    23.两两交换链表中的两个节点题目链接文章讲解视频讲解时间复杂度o(n)空间复杂度o(1)tips:画图,并将每一步操作用伪代码写出来,然后将代码理顺可以避免修改代码的麻烦初始化的时候就要将previous初始化为current的前一个节点,这样可以保证循环的第一步满足循环要求cla......
  • 代码随想录算法训练营第第二天 | 24. 两两交换链表中的节点 、19.删除链表的倒数第N
    两两交换链表中的节点用虚拟头结点,这样会方便很多。本题链表操作就比较复杂了,建议大家先看视频,视频里我讲解了注意事项,为什么需要temp保存临时节点。题目链接/文章讲解/视频讲解:https://programmercarl.com/0024.两两交换链表中的节点.html/***Definitionforsingly-li......
  • 读天才与算法:人脑与AI的数学思维笔记25_涌现理论
    1. 人工智能新闻1.1. 人工智能新闻报道算法的核心是如何将未经处理的原始数据转换成新闻报道1.2. 很少有记者为美联社决定使用机器来帮助报道这些新闻持反对意见1.2.1. 像“Wordsmith”这样的算法,具有自动化的洞察力、科学的叙事能力,现在正被应用于基于大量数据的分析报道......
  • 算法之数学知识
    威尔逊定理:如果p是指数,那么(p-1)!对于p取模恒等于p-1.逆元的概念及其求解方法https://blog.csdn.net/weixin_40895249/article/details/124477029?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171394439916800188566032%2522%252C%2522scm%2522%253A%25222014071......