首页 > 其他分享 >洛谷P4146 序列终结者 题解 splay tree

洛谷P4146 序列终结者 题解 splay tree

时间:2022-12-31 22:07:42浏览次数:70  
标签:sz 洛谷 int 题解 void tree tr add push

题目链接:​​https://www.luogu.com.cn/problem/P4146​

题目大意:

支持:

  • 区间更新(+x)
  • 区间翻转
  • 区间查询(最大值)

解题思路:几乎和 ​​AcWing2437. Splay​​ 这题一模一样。

示例程序:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e5 + 5;
const int INF = (1LL<<60);

int n, m;
struct Node {
int s[2], p, v;
int sz, flag, mx, add;

Node() {};
Node(int _v, int _p) {v = _v; p = _p; s[0] = s[1] = 0; flag = 0; sz = 1; mx = v; add = 0;}
} tr[maxn];
int root, idx;

void push_up(int x) {
tr[x].sz = tr[tr[x].s[0]].sz + tr[tr[x].s[1]].sz + 1;
tr[x].mx = max(tr[x].v, max(tr[tr[x].s[0]].mx, tr[tr[x].s[1]].mx));
}

void t_swap(int x) {
tr[x].flag ^= 1;
swap(tr[x].s[0], tr[x].s[1]);
}

void t_add(int x, int d) {
tr[x].v += d;
tr[x].mx += d;
tr[x].add += d;
}

void push_down(int x) {
if (tr[x].flag) {
t_swap(tr[x].s[0]);
t_swap(tr[x].s[1]);
tr[x].flag = 0;
}
if (tr[x].add) {
t_add(tr[x].s[0], tr[x].add);
t_add(tr[x].s[1], tr[x].add);
tr[x].add = 0;
}
}

void f_s(int p, int u, bool k) {
tr[p].s[k] = u;
tr[u].p = p;
}

void rot(int x) {
int y = tr[x].p, z = tr[y].p;
bool k = tr[y].s[1] == x;
f_s(z, x, tr[z].s[1]==y);
f_s(y, tr[x].s[k^1], k);
f_s(x, y, k^1);
push_up(y), push_up(x);
}

void splay(int x, int k) {
while (tr[x].p != k) {
int y = tr[x].p, z = tr[y].p;
if (z != k)
(tr[y].s[1]==x) ^ (tr[z].s[1]==y) ? rot(x) : rot(y);
rot(x);
}
if (!k) root = x;
}

int get_k(int k) {
int u = root;
while (u) {
push_down(u);
if (tr[tr[u].s[0]].sz >= k) u = tr[u].s[0];
else if (tr[tr[u].s[0]].sz + 1 == k) return u;
else k -= tr[tr[u].s[0]].sz + 1, u = tr[u].s[1];
}
return -1;
}

int build(int l, int r, int p) {
int x = ++idx;
int v = (l < 1 || l > n) ? -INF : 0;
tr[x] = Node(v, p);
int mid = (l + r) / 2;
if (l < mid) tr[x].s[0] = build(l, mid-1, x);
if (r > mid) tr[x].s[1] = build(mid+1, r, x);
push_up(x);
return x;
}

void init() {
tr[0] = Node(0, 0);
tr[0].sz = 0;
tr[0].mx = -INF;
}

signed main() {
init();
cin >> n >> m;
root = build(0, n+1, 0);
while (m--) {
int op, l, r, x;
cin >> op >> l >> r;
l = get_k(l), r = get_k(r+2);
splay(l, 0), splay(r, l);
push_down(l), push_down(r);
if (op == 1) {
cin >> x;
t_add(tr[r].s[0], x);
}
else if (op == 2) {
t_swap(tr[r].s[0]);
}
else {
cout << tr[tr[r].s[0]].mx << endl;
}
}
return 0;
}



标签:sz,洛谷,int,题解,void,tree,tr,add,push
From: https://blog.51cto.com/u_13536312/5982388

相关文章

  • 洛谷 P5721 【深基4.例6】数字直角三角形
    题目描述给出nn,请输出一个直角边长度是nn的数字直角三角形。所有数字都是22位组成的,如果没有22位则加上前导00。输入格式输入一个正整数nn。输出格式输出如......
  • CF1770D Koxia and Game 题解
    47min时过C降智50min做不出D。果然晚上容易降智。题意不想复述,好长。linktoCF|linktoLuogu合理猜测留给后手的两个数字必须相等。证明为若不相等,则后手可以......
  • 洛谷 P2395 BBCode转换Markdown 题解
    洛谷P2395BBCode转换Markdown题解题目传送门:here.一道毒瘤的大模拟,给了你一部分的BBCode和Markdown语法,叫你转换。如下表:BBCodeMarkdown[h1]文字[/h1......
  • AcWing 1359. 洛谷P1457 城堡
    解题思路\(\qquad\)这道题目是需要维护各种连通块信息的,所以这里我们可以也用并查集维护。这题我们如果注意一点细节,也是可以让代码变得很简洁的:\(\qquad\quad1.\)这道......
  • Codeforces Good Bye 2022 CF 1770 A~E 题解
    题目链接A.KoxiaandWhiteboards注意每一步替换操作都是强制的,而不是可选的。所以就用一个multiset维护所有的数,每次选一个最小的替换掉即可。时间复杂度\(O(nlogn)\)......
  • P4247 [清华集训2012]序列操作 题解
    线段树练手好题。直接上线段树五问:维护的信息是什么?由于\(c\le20\),我们不妨对线段树的每个节点维护一个\(f_k\)表示在对应区间里选择\(k\)个数相乘的所有方案的和......
  • 题解 CF1770B【Koxia and Permutation】
    \(k=1\)的情况是平凡的。\(k>1\)的情况,显然答案至少为\(n+1\),下面给出构造证明\(n+1\)总可以取到。可以构造\(p=[n,1,n-1,2,n-2,3,\cdots]\),此时以\(n\)作为最......
  • 题解 CF1770C【Koxia and Number Theory】
    显然,如果存在\(a_i=a_j\),则一定无解。否则,考虑每一个\(2\sim50\)的正整数\(k\),如果原数组每个数对\(k\)取模后,每种余数都出现至少两次,则无解。因为此时无论如何选......
  • 【题解】P5574 [CmdOI2019]任务分配问题
    stocmd学长orz题意P5574[CmdOI2019]任务分配问题给定一个长度为\(n\)的排列,试将它分成\(k\)段,使得每段的顺序对数量之和最小。\(n\leq2.5\times10^4,k\l......
  • 【题解】P1912 [NOI2009] 诗人小G
    题意多测。给定\(n\)个字符串和一个常数\(L\),试将这些字符串分成若干组,使得:令\(len(i)\)为第\(i\)个字符串的长度,则每组字符串的\(|\sum\limitslen(i)-L|\)......