这里介绍以个小$trick$,民间流传为$Old Driver Tree$,实质上就是$set$维护线段。

我们将所有连续一段权值相同的序列合并成一条线段,扔到$set$里去,于是$set$里的所有线段的并就是原序列,并且都不相交。

我们在操作的时候很暴力,每次把$[l, r]$的线段抠出来,暴力枚举一遍算答案。对于每一个非区间赋值的操作,最多断两条线段,新加两条线段。

实现起来很方便,思路也非常简单,但是局限性也很明显,因为其复杂度是基于随机的,并且必须存在区间赋值的操作。

但$set$维护线段的技巧还是很常见的,我用$set$和$map$都实现的一遍,发现这里用$map$相当好写。

$set$的实现:

#include <set>
#include <cstdio>
#include <algorithm>
using namespace std; typedef long long LL;
const int N = ; int n, m, vmax, tp;
pair<LL, int> st[N]; struct Seg {
int l, r; LL v;
friend bool operator < (Seg a, Seg b) {
return (a.l != b.l)? (a.l < b.l) : (a.r < b.r);
}
};
multiset<Seg> S;
typedef multiset<Seg>::iterator Saber; LL Pow(LL x, int b, int p, LL re = ) {
for (x %= p; b; b >>= , x = x * x % p)
if (b & ) re = re * x % p;
return re;
} namespace R {
const int mod = 1e9 + ;
int seed, ret;
int rnd() {
ret = seed;
seed = (seed * 7LL + ) % mod;
return ret;
}
} int main() {
scanf("%d%d%d%d", &n, &m, &R::seed, &vmax);
for (int i = ; i <= n; ++i)
S.insert((Seg){ i, i, R::rnd() % vmax + });
for (int op, l, r, x, y; m; --m) {
op = (R::rnd() & ) + ;
l = R::rnd() % n + ;
r = R::rnd() % n + ;
if (l > r) swap(l, r);
if (op == ) x = R::rnd() % (r - l + ) + ;
else x = R::rnd() % vmax + ;
if (op == ) y = R::rnd() % vmax + ; Saber p = --S.lower_bound((Seg){ l + , , });
Saber q = --S.lower_bound((Seg){ r + , , });
if ((*p).l < l) S.insert((Seg){ (*p).l, l - , (*p).v });
if (r < (*q).r) S.insert((Seg){ r + , (*q).r, (*q).v });
if (op == ) {
for (Saber z = p, rin; z != q; ) {
rin = z; ++z;
S.erase(rin);
}
S.erase(q);
S.insert((Seg){ l, r, x });
continue;
}
Saber np, nq;
if (p == q) {
np = nq = S.insert((Seg){ l, r, (*p).v });
S.erase(p);
} else {
np = S.insert((Seg){ l, (*p).r, (*p).v });
nq = S.insert((Seg){ (*q).l, r, (*q).v });
S.erase(p); S.erase(q);
}
if (op == ) {
Seg ins;
for (Saber z = np, rin; z != nq; ) {
rin = z; ++z;
ins = *rin; ins.v += x;
S.erase(rin); S.insert(ins);
}
ins = *nq; ins.v += x;
S.erase(nq); S.insert(ins);
}
if (op == ) {
tp = ;
for (Saber z = np; z != nq; ++z)
st[++tp] = make_pair((*z).v, (*z).r - (*z).l + );
st[++tp] = make_pair((*nq).v, (*nq).r - (*nq).l + );
sort(st + , st + + tp);
for (int i = ; i <= tp; x -= st[i].second, ++i) {
if (st[i].second >= x) {
printf("%lld\n", st[i].first);
x = ;
break;
}
}
if (x > ) {
puts("I love you, love you forever.");
return ;
}
}
if (op == ) {
int ans = ;
for (Saber z = np; z != nq; ++z)
ans = (ans + Pow((*z).v, x, y) * ((*z).r - (*z).l + )) % y;
ans = (ans + Pow((*nq).v, x, y) * ((*nq).r - (*nq).l + )) % y;
printf("%d\n", ans);
}
} return ;
}

$map$的实现:

#include <map>
#include <cstdio>
#include <algorithm>
using namespace std; typedef long long LL;
const int N = ; int n, m, vmax, tp;
pair<LL, int> st[N];
map<int, LL> M; LL Pow(LL x, int b, int p, LL re = ) {
for (x %= p; b; b >>= , x = x * x % p)
if (b & ) re = re * x % p;
return re;
} namespace R {
const int mod = 1e9 + ;
int seed, ret;
int rnd() {
ret = seed;
seed = (seed * 7LL + ) % mod;
return ret;
}
} int main() {
scanf("%d%d%d%d", &n, &m, &R::seed, &vmax);
for (int i = ; i <= n; ++i)
M[i] = R::rnd() % vmax + ;
M[n + ] = ;
for (int op, l, r, x, y; m; --m) {
op = (R::rnd() & ) + ;
l = R::rnd() % n + ;
r = R::rnd() % n + ;
if (l > r) swap(l, r);
if (op == ) x = R::rnd() % (r - l + ) + ;
else x = R::rnd() % vmax + ;
if (op == ) y = R::rnd() % vmax + ; auto p = --M.upper_bound(l);
auto q = M.upper_bound(r);
if (p->first < l) M[l] = p->second, ++p;
if (r + < q->first) --q, M[r + ] = q->second, ++q;
if (op == ) {
for (; p != q; ++p) p->second += x;
}
if (op == ) {
while (p != q) M.erase(p++);
M[l] = x;
}
if (op == ) {
tp = ;
for (auto rin = p; p != q; ++p) {
st[++tp] = { p->second, (++rin)->first - p->first };
}
sort(st + , st + + tp);
for (int i = ; i <= tp; x -= st[i].second, ++i) {
if (x <= st[i].second) {
printf("%lld\n", st[i].first);
break;
}
}
}
if (op == ) {
int ans = ;
for (auto rin = p; p != q; ++p) {
ans = (ans + Pow(p->second, x, y) * ((++rin)->first - p->first)) % y;
}
printf("%d\n", ans);
}
} return ;
}

【Cf #449 C】Willem, Chtholly and Seniorious(set维护线段)的更多相关文章

  1. CF&&CC百套计划1 Codeforces Round #449 C. Willem, Chtholly and Seniorious (Old Driver Tree)

    http://codeforces.com/problemset/problem/896/C 题意: 对于一个随机序列,执行以下操作: 区间赋值 区间加 区间求第k小 区间求k次幂的和 对于随机序列, ...

  2. Codeforces Round #449 (Div. 1) Willem, Chtholly and Seniorious (ODT维护)

    题意 给你一个长为 \(n\) 的序列 \(a_i\) 需要支持四个操作. \(1~l~r~x:\) 把 \(i \in [l, r]\) 的 \(a_i\) 加 \(x\) . \(2~l~r~x: ...

  3. Willem, Chtholly and Seniorious

    Willem, Chtholly and Seniorious https://codeforces.com/contest/897/problem/E time limit per test 2 s ...

  4. Codeforces Round #449 (Div. 1)C - Willem, Chtholly and Seniorious

    ODT(主要特征就是推平一段区间) 其实就是用set来维护三元组,因为数据随机所以可以证明复杂度不超过O(NlogN),其他的都是暴力维护 主要操作是split,把区间分成两个,用lowerbound ...

  5. 【ODT】cf896C - Willem, Chtholly and Seniorious

    仿佛没用过std::set Seniorious has n pieces of talisman. Willem puts them in a line, the i-th of which is ...

  6. [Codeforces896C] Willem, Chtholly and Seniorious (ODT-珂朵莉树)

    无聊学了一下珂朵莉树 珂朵莉树好哇,是可以维护区间x次方和查询的高效数据结构. 思想大致就是一个暴力(相对而言)的树形数据结构 lxl毒瘤太强了,发明了ODT算法(Old Driver Tree老司机 ...

  7. [CF896C]Willem, Chtholly and Seniorious(珂朵莉树)

    https://www.cnblogs.com/WAMonster/p/10181214.html 主要用于支持含有较难维护的区间操作与查询的问题,要求其中区间赋值操作(assign())是纯随机的. ...

  8. 2019.01.19 codeforces896C.Willem, Chtholly and Seniorious(ODT)

    传送门 ODTODTODT出处(万恶之源) 题目简述: 区间赋值 区间加 区间所有数k次方和 区间第k小 思路:直接上ODTODTODT. 不会的点这里 代码: #include<bits/st ...

  9. cf896C. Willem, Chtholly and Seniorious(ODT)

    题意 题目链接 Sol ODT板子题.就是用set维护连续段的大暴力.. 然鹅我抄的板子本题RE提交AC??.. 具体来说,用50 50 658073485 946088556这个数据测试下面的代码, ...

随机推荐

  1. Datawhale MySQL 训练营 Task4 表联结

    学习内容 MySQL别名 列别名,将查询或者筛选出来列用AS 命名,如果有空格则需要引号 '' SELECT xxx AS xxxx FROM WHERE GROUP BY HAVING 表别名, 把 ...

  2. django1.11入门

    快速安装指南¶ 在使用Django之前,您需要安装它.我们有 完整的安装指南,涵盖所有可能性; 本指南将指导您进行简单,最小化的安装,在您完成介绍时可以正常工作. 安装Python¶ 作为一个Pyth ...

  3. docker usage

    docker ps -a 查看物理机上面所有容器信息列表 docker exec -it $docker_id /bin/bash 进入容器以默认帐号 docker exec -it -u root ...

  4. wc命令详解

    基础命令学习目录首页 原文链接:http://www.cnblogs.com/peida/archive/2012/12/18/2822758.html Linux系统中的wc(Word Count) ...

  5. Daily Scrum (2015/10/31)

    这几天我们组的进度有点慢,剩下这一周的我们必须要加油认真对待. 周末这两天我们是这样安排的: 成员 今日任务 时间 明日任务 符美潇 数据库部分代码的编写 1h 每周小组例会 潘礼鹏 团队博客作业   ...

  6. iOS自学-混合编程

    OC调用swift,引入头文件 #improt "工程名字-swift.h" swift调用OC,在桥梁文件里面引入OC文件 的头文件 尽情混合编程吧...

  7. 2018软工实践—Beta冲刺(6)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Beta 冲鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调组内工作 最终测试文稿编写 展示GitHub当日代码/文档签入记录 ...

  8. shiro+springmvc 都使用缓存

    基于涛哥shiro案例16 的这时候要配置service方法的缓存 在spring-config.xml添加 <context:annotation-config /> <cache ...

  9. IO流的各种继承关系

  10. Python开发【第五篇】迭代器、生成器、递归函数、二分法

    阅读目录 一.迭代器 1. 迭代的概念 #迭代器即迭代的工具(自定义的函数),那什么是迭代呢? #迭代:指一个重复的过程,每次重复都可以称之为一次迭代,并且每一次重复的结果是下一个迭代的初始值(例如: ...