这个星期打了一些splay, 下面在这里做下总结吧。
splay 的核心 要实现的就是 把二叉排序树中的一个节点移到它的某个祖先节点的位置。
/*
这个操作初看来可能没有什么实际的用途,但是仔细思考简直是 非常方便。
当我们需要对一个区间进行操作时, 只要把这个区间的左端点的前一个点和右端点的后一个点 分别旋到 根节点和 根节点 的右儿子节点, 这时候一个感人肺腑的现象就出现了: 以根节点的右儿子节点的左儿子节点为根的这棵树就是 所询问的线段。画个图是很显然的。
有了这个操作后很多东西就都可以迎刃而解了。
其实splay比线段树好的地方大概也就是 这里, 即它对区间 的灵活性。
总结splay可以多实现的东西我目前大概只知道这三个:插入一个区间, 删除一个区间, 翻转一个区间。
*/
下面看实现,
最暴力的方法就是 把以目标节点为根的子树拆了 然后 从新 建,但是容易发现有一种更加便捷的方法就是把 当前节点一层一层地旋上去。
这里使用的是双旋, 所以分为两种情况: 父亲就是目标节点, 直接转上去就好了; 父亲不是目标节点, 根据当前节点 和当前 节点的父节点 是否同是自身父节点的左(右)儿子再分成两种情况讨论: 如果 左右性相同, 先把父节点向上转, 再把当前节点向上转; 如果左右性不同, 就把当前节点向上转两次。 (转法 不唯一, 只要可以把当前节点转到父节点的父节点就可以了)。
下面处理刚才说的那个旋转。 如果把一个点向右上旋, 当前节点右儿子的 位置肯定就会被 当前节点的父节点占领, 哪怎么办呢? 显然这里多出来了一个点就一定有一个地方少了一个点—— 原来的父节点的 左儿子 (即当前节点)现在没有了, 于是自然要把多出来的这个接上去, 考虑 二叉排序树的性质这样接时没有问题的。显然在旋转后 , 当前节点变成了原先的父节点的父节点, 变成了原先的父节点的父节点 的子节点, 所以再把这两层关系分别处理一下就好了。
以上就是splay全部的核心思想了, 具体实现时 考虑左右的对称性 可以把左旋和右旋放到一个函数里写, 一个 k 等于1时是右旋, 等于0时是左旋。
实现起来极其简单。 只有简洁优美的十几行。
void jie(int x, int y, int k){if(y)ch[y][k] = x; fat[x] = y;}
void rotate(int x, int k){
int y = fat[x];
jie(ch[x][k], y, !k),jie(x, fat[y], ch[fat[y]][1] == y),jie(y, x, k);
}
void splay(int x, int goal){
while(fat[x] != goal){
if(fat[fat[x]] == goal){rotate(x, ch[fat[x]][0] == x); break;}
int y = fat[x], ky = ch[fat[y]][1] == y;
if(ch[y][ky] == x)rotate(y, !ky), rotate(x, !ky);
else rotate(x, ky), rotate(x, !ky);
}
if(!goal)root = x;
}
虽然splay操作真的很短, 但是考虑到简单的操作用线段树就可以了, 所以splay的题一般会出很多种操作, 分一下类就会觉得代码很长, 其实没有什么的, 也就是维护一个二叉排序树的各种性质。
先上几道可以用线段树等较简单方法实现的题来巩固对splay的理解。
这道题相信没人 没有用线段树做过, 因为什么操作都没有所以用splay打也超级短啊! 短的令人想哭。
<pre style="font-family:Courier New;text-align:left;"><span style="color:blue;">#include <iostream>
#include <cstdio>
#define MAXN 200005
</span><strong><span style="color:#0000FF;">using namespace</span></strong> std<strong><span style="color:#FF00FF;">;</span><span style="color:blue;">
int</span></strong> n<strong><span style="color:#FF00FF;">,</span></strong> q<strong><span style="color:#FF00FF;">,</span></strong> num<strong><span style="color:#FF00FF;">[</span></strong>MAXN<strong><span style="color:#FF00FF;">],</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>MAXN<strong><span style="color:#FF00FF;">],</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>MAXN<strong><span style="color:#FF00FF;">],</span></strong> root<strong><span style="color:#FF00FF;">,</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>MAXN<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">2</span><strong><span style="color:#FF00FF;">];</span><span style="color:blue;">
void</span></strong> pushup<strong><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> x<strong><span style="color:#FF00FF;">){</span></strong>maxx<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">] =</span></strong> max<strong><span style="color:#FF00FF;">(</span></strong>num<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">],</span></strong> max<strong><span style="color:#FF00FF;">(</span></strong>maxx<strong><span style="color:#FF00FF;">[</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">]],</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">]]));}</span><span style="color:blue;">
void</span></strong> jie<strong><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> x<strong><span style="color:#FF00FF;">,</span><span style="color:blue;"> int</span></strong> y<strong><span style="color:#FF00FF;">,</span><span style="color:blue;"> int</span></strong> k<strong><span style="color:#FF00FF;">){</span><span style="color:#0000FF;">if</span><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;">)</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">][</span></strong>k<strong><span style="color:#FF00FF;">] =</span></strong> x<strong><span style="color:#FF00FF;">;</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">] =</span></strong> y<strong><span style="color:#FF00FF;">;}</span><span style="color:blue;">
void</span></strong> rotate<strong><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> x<strong><span style="color:#FF00FF;">,</span><span style="color:blue;"> int</span></strong> k<strong><span style="color:#FF00FF;">){</span><span style="color:blue;">
int</span></strong> y<strong><span style="color:#FF00FF;"> =</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">];</span></strong>
jie<strong><span style="color:#FF00FF;">(</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">][</span></strong>k<strong><span style="color:#FF00FF;">],</span></strong> y<strong><span style="color:#FF00FF;">, !</span></strong>k<strong><span style="color:#FF00FF;">),</span></strong>jie<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">,</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">],</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">]][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] ==</span></strong> y<strong><span style="color:#FF00FF;">),</span></strong>jie<strong><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;">,</span></strong> x<strong><span style="color:#FF00FF;">,</span></strong> k<strong><span style="color:#FF00FF;">);</span></strong>
pushup<strong><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;">);
}</span><span style="color:blue;">
void</span></strong> splay<strong><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> x<strong><span style="color:#FF00FF;">,</span><span style="color:blue;"> int</span></strong> goal<strong><span style="color:#FF00FF;">){</span><span style="color:#0000FF;">
while</span><span style="color:#FF00FF;">(</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">] !=</span></strong> goal<strong><span style="color:#FF00FF;">){</span><span style="color:#0000FF;">
if</span><span style="color:#FF00FF;">(</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">]] ==</span></strong> goal<strong><span style="color:#FF00FF;">){</span></strong>rotate<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">,</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">]][</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">] ==</span></strong> x<strong><span style="color:#FF00FF;">);</span><span style="color:#0000FF;"> break</span><span style="color:#FF00FF;">;}</span><span style="color:blue;">
int</span></strong> y<strong><span style="color:#FF00FF;"> =</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">],</span></strong> ky<strong><span style="color:#FF00FF;"> =</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">]][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] ==</span></strong> y<strong><span style="color:#FF00FF;">;</span><span style="color:#0000FF;">
if</span><span style="color:#FF00FF;">(</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">][</span></strong>ky<strong><span style="color:#FF00FF;">] ==</span></strong> x<strong><span style="color:#FF00FF;">)</span></strong>rotate<strong><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;">, !</span></strong>ky<strong><span style="color:#FF00FF;">),</span></strong> rotate<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">, !</span></strong>ky<strong><span style="color:#FF00FF;">);</span><span style="color:#0000FF;">
else</span></strong> rotate<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">,</span></strong> ky<strong><span style="color:#FF00FF;">),</span></strong> rotate<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">, !</span></strong>ky<strong><span style="color:#FF00FF;">);
}</span></strong>pushup<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">);</span><span style="color:#0000FF;">
if</span><span style="color:#FF00FF;">(!</span></strong>goal<strong><span style="color:#FF00FF;">)</span></strong>root<strong><span style="color:#FF00FF;"> =</span></strong> x<strong><span style="color:#FF00FF;">;
}</span><span style="color:blue;">
int</span><span style="color:#0000FF;"> main</span><span style="color:#FF00FF;">()
{</span><span style="color:#0000FF;">
while</span><span style="color:#FF00FF;">(</span></strong>scanf<strong><span style="color:#FF00FF;">(</span></strong><span style="color:green;">"%d%d"</span><strong><span style="color:#FF00FF;">, &</span></strong>n<strong><span style="color:#FF00FF;">, &</span></strong>q<strong><span style="color:#FF00FF;">) !=</span></strong> EOF<strong><span style="color:#FF00FF;">){</span><span style="color:#0000FF;">
for</span><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> i<strong><span style="color:#FF00FF;"> =</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">;</span></strong> i<strong><span style="color:#FF00FF;"> <=</span></strong> n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">;</span></strong> i<strong><span style="color:#FF00FF;"> ++)</span></strong>scanf<strong><span style="color:#FF00FF;">(</span></strong><span style="color:green;">"%d"</span><strong><span style="color:#FF00FF;">, &</span></strong>num<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">]);</span></strong> num<strong><span style="color:#FF00FF;">[</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] =</span></strong> num<strong><span style="color:#FF00FF;">[</span></strong>n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">] = -</span></strong><span style="color:#CC3300;">100000000</span><strong><span style="color:#FF00FF;">;</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 3</span><strong><span style="color:#FF00FF;">] =</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">;</span><span style="color:#0000FF;">
for</span><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> i<strong><span style="color:#FF00FF;"> =</span></strong> n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">;</span></strong> i<strong><span style="color:#FF00FF;">;</span></strong> i<strong><span style="color:#FF00FF;"> --){</span></strong>
ch<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">] =</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">; (</span></strong>i<strong><span style="color:#FF00FF;"> ==</span></strong> n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;"> )?</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] =</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;"> :</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] =</span></strong> i<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">;</span></strong>
fat<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">] =</span></strong> i<strong><span style="color:#FF00FF;"> -</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">;</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">] =</span></strong> max<strong><span style="color:#FF00FF;">(</span></strong>maxx<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">],</span></strong> num<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">]);
}</span></strong> root<strong><span style="color:#FF00FF;"> =</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">;</span><span style="color:#0000FF;">
while</span><span style="color:#FF00FF;">(</span></strong>q<strong><span style="color:#FF00FF;"> --){</span><span style="color:blue;">
char</span></strong> s<strong><span style="color:#FF00FF;">[</span></strong><span style="color:#CC3300;">5</span><strong><span style="color:#FF00FF;">];</span><span style="color:blue;"> int</span></strong> x<strong><span style="color:#FF00FF;">,</span></strong> y<strong><span style="color:#FF00FF;">;</span></strong> scanf<strong><span style="color:#FF00FF;">(</span></strong><span style="color:green;">"%s%d%d"</span><strong><span style="color:#FF00FF;">,</span></strong> s<strong><span style="color:#FF00FF;">, &</span></strong>x<strong><span style="color:#FF00FF;">, &</span></strong>y<strong><span style="color:#FF00FF;">);</span></strong>x<strong><span style="color:#FF00FF;"> ++;</span><span style="color:#0000FF;">
if</span><span style="color:#FF00FF;">(</span></strong>s<strong><span style="color:#FF00FF;">[</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">] ==</span></strong><span style="color:green;"> 'U'</span><strong><span style="color:#FF00FF;">)</span></strong>splay<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">,</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">),</span></strong>num<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">] =</span></strong> y<strong><span style="color:#FF00FF;">,</span></strong> pushup<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">);</span><span style="color:#0000FF;">
else</span></strong> splay<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;"> -</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">,</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">),</span></strong> splay<strong><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">,</span></strong> x<strong><span style="color:#FF00FF;"> -</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">),</span></strong> printf<strong><span style="color:#FF00FF;">(</span></strong><span style="color:green;">"%d\n"</span><strong><span style="color:#FF00FF;">,</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">]]);
}
}</span><span style="color:#0000FF;">
return</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">;
}</span></strong>
poj 3468 a simple promble with integers
同裸线段树经典题。多了一个修改操作。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define MAXN 100005
using namespace std;
int n, q, root, num[MAXN], ch[MAXN][2], fat[MAXN], r[MAXN], sz[MAXN];
long long summ[MAXN];
inline void jie(int x, int y, int k){if(y)ch[y][k] = x; fat[x] = y;}
inline void pushup(int x){
sz[x] = sz[ch[x][1]] + sz[ch[x][0]] + 1;
summ[x] = r[x] + num[x] + summ[ch[x][0]] + summ[ch[x][1]];
}
inline void pushdown(int x){
if(!r[x])return;
num[x] += r[x];
r[ch[x][0]] += r[x]; r[ch[x][1]] += r[x];
summ[ch[x][0]] += (long long)sz[ch[x][0]] * r[x];
summ[ch[x][1]] += (long long)sz[ch[x][1]] * r[x];
r[x] = 0;
}
inline void rotate(int x, int k){
int y = fat[x]; pushdown(y); pushdown(x);
jie(ch[x][k], y, !k), jie(x, fat[y], ch[fat[y]][1] == y), jie(y, x, k);
pushup(y);
}
inline void splay(int x, int goal){
pushdown(x);
while(fat[x] != goal){
if(fat[fat[x]] == goal){ rotate(x, ch[fat[x]][0] == x); break;}
int y = fat[x], ky = ch[fat[y]][1] == y;
if(ch[y][ky] == x)rotate(y, !ky), rotate(x, !ky);
else rotate(x, ky), rotate(x, !ky);
} pushup(x);
if(! goal)root = x;
}
int main(){
scanf("%d%d", &n, &q);
for(int i = 2; i <= n + 1; i ++)scanf("%d", &num[i]); fat[n + 2] = n + 1;
for(int i = n + 1; i; i --){ch[i][1] = i + 1; summ[i] = summ[i + 1] + num[i]; sz[i] = sz[i + 1] + 1; fat[i] = i - 1;}
root = 1;
while(q --){
char s[5]; int x, y, z; scanf("%s%d%d", s, &x, &y);x ++; y ++;
if(s[0] == 'Q')splay(x - 1, 0), splay(y + 1, x - 1), cout<<summ[ch[y + 1][0]]<<endl;
else{scanf("%d", &z);
splay(x - 1, 0); splay(y + 1, x - 1);
r[ch[y + 1][0]] += z;
summ[ch[y + 1][0]] += (long long)z * sz[ch[y + 1][0]];
}
}
return 0;
}
所以这次又新增了一个插入操作。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#define MAXN 100005
#define INF 1<<30
using namespace std;
int n, num, ch[MAXN][2], a[MAXN], cnt, root, ans, fat[MAXN];
void addnode(int father, int k){
a[++ cnt] = k;
fat[cnt] = father;
}
void rotate(int x, int kind){
int f = fat[x];
ch[f][!kind] = ch[x][kind];
fat[ch[x][kind]] = f;
//if(fat[f])
ch[fat[f]][ch[fat[f]][1] == f] = x;
fat[x] = fat[f];
ch[x][kind] = f;
fat[f] = x;
}
void splay(int r){
while(fat[r]){
if(!fat[fat[r]]){rotate(r, ch[fat[r]][1] != r); continue;}
int f = fat[r];
int kindf = ch[fat[f]][1] == f;
if(ch[f][kindf] == r)rotate(f, !kindf), rotate(r, !kindf);
else rotate(r, kindf), rotate(r, !kindf);
} root = r;
}
int insert(int k){
int r = root;
while(ch[r][a[r] < k]){
if(a[r] == k){splay(r); return 0;}
r = ch[r][a[r] < k];
}
ch[r][a[r] < k] = cnt + 1;
addnode(r, k);
splay(cnt); return 1;
}
int get(int x, int k){
int tmp = ch[x][!k];
if(!tmp)return INF;
while(ch[tmp][k])tmp = ch[tmp][k];
return abs(a[tmp] - a[x]);
}
int main()
{
//freopen("1588.in", "r", stdin);
scanf("%d%d", &n, &num);
root = 1; addnode(0, num); ans += num;
for(int i = 2; i <= n; i ++){
num = 0; scanf("%d", &num);
if(! insert(num))continue;
ans += min(get(root, 0), get(root, 1));
}cout<<ans<<endl;
return 0;
}
所以这次又新增了删除操作。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define MAXN 200005
using namespace std;
int n, minn, minn0, x, sz[MAXN], ch[MAXN][2], pre[MAXN], cnt[MAXN], val[MAXN], summ, rt, top;
inline void pushup(int x){sz[x] = cnt[x] + sz[ch[x][0]] + sz[ch[x][1]];}
inline void jie(int y, int x, int k){if(y)ch[y][k] = x; pre[x] = y;}
inline void rotate(int x, int k){
int y = pre[x];jie(y, ch[x][k], !k);
jie(pre[y], x, ch[pre[y]][1] == y);
jie(x, y, k);
pushup(y);
}
inline void splay(int x, int goal){
while(pre[x] != goal){
if(pre[pre[x]] == goal){rotate(x, ch[pre[x]][0] == x); break;}
int y = pre[x], kf = ch[pre[y]][1] == y;
if(ch[y][kf] == x)rotate(y, !kf), rotate(x, !kf);
else rotate(x, kf), rotate(x, !kf);
} pushup(x);
if(!goal)rt = x;
}
inline void newnode(int &x, int c){
x = ++ top;
sz[x] = 1; cnt[x] = 1; val[x] = c;
}
inline void insert(int &x, int key, int f){
if(!x){
newnode(x, key);
pre[x] = f;
splay(x, 0); return;
}
if(key == val[x]){
cnt[x] ++; sz[x] ++;
splay(x, 0); return ;
}
if(key < val[x])insert(ch[x][0], key, x);
else insert(ch[x][1], key, x);
pushup(x);
}
inline void del(int &x, int f){
if(!x)return;
if(val[x] >= minn) del(ch[x][0], x);
else{
summ += sz[ch[x][0]] + cnt[x];
x = ch[x][1];
pre[x] = f;
if(f == 0)rt = x;
del(x, f);
} if(x)pushup(x);
}
inline int findk(int x, int k){//cout<<x<<endl;
if(k < sz[ch[x][0]] + 1)return findk(ch[x][0], k);
if(k > sz[ch[x][0]] + cnt[x])return findk(ch[x][1], k - sz[ch[x][0]] - cnt[x]);
splay(x, 0); return val[x];
}
int main(){
scanf("%d%d", &n, &minn); minn0 = minn;
char s[10]; int k;
while(n --){
scanf("%s%d", s, &k);
if(s[0] == 'A')minn -= k;
if(s[0] == 'S'){
minn += k;
if(sz[rt])del(rt, 0);
}
if(s[0] == 'I' && k >= minn0)insert(rt, k + minn - minn0, 0);
if(s[0] == 'F'){
if(k > sz[rt])puts("-1");
else printf("%d\n", findk(rt, sz[rt] - k + 1) - minn + minn0);
}
}cout<<summ<<endl;
return 0;
}
这时候有了修改操作, 自然要用到懒标记, 懒标记的pushup 和pushdown和线段树基本相同。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define MAXN 100005
using namespace std;
int n, p, la, a, b, c;
struct Tree{
int l, r;long long plus, mul, summ;
}tree[MAXN * 4];
inline void pushup(int t){tree[t].summ = (tree[t + t].summ + tree[t + t + 1].summ) % p;}
inline void pushdown(int t){
tree[t + t].plus = (tree[t + t].plus * tree[t].mul + tree[t].plus) % p;
tree[t + t + 1].plus = (tree[t + t + 1].plus * tree[t].mul + tree[t].plus) % p;
tree[t + t].mul = tree[t + t].mul * tree[t].mul % p;
tree[t + t + 1].mul = tree[t + t + 1].mul * tree[t].mul % p;
tree[t + t].summ = (tree[t + t].summ * tree[t].mul + tree[t].plus * (tree[t + t].r - tree[t + t].l + 1)) % p;
tree[t + t + 1].summ = (tree[t + t + 1].summ * tree[t].mul + tree[t].plus * (tree[t + t + 1].r - tree[t + t + 1].l + 1)) % p;
tree[t].plus = 0; tree[t].mul = 1;
}
void build(int l, int r, int t){
tree[t].l = l; tree[t].r = r;
tree[t].plus = 0; tree[t].mul = 1;
if(l == r){scanf("%lld", &tree[t].summ); return;}
int mid = l + r >> 1;
build(l, mid, t + t); build(mid + 1, r, t + t + 1);
pushup(t);
}
void alter(int t, int l, int r){
if(tree[t].l >= l && tree[t].r <= r){
if(la == 1){
tree[t].plus = tree[t].plus * c % p;
tree[t].mul = tree[t].mul * c % p;
tree[t].summ = tree[t].summ * c % p;
}else{
tree[t].plus = (tree[t].plus + c) % p;
tree[t].summ = (tree[t].summ + (long long)c * (tree[t].r - tree[t].l + 1)) % p;
}
return;
}pushdown(t);
int mid = tree[t].l + tree[t].r >> 1;
if(mid >= l)alter(t + t, l, r);
if(mid < r)alter(t + t + 1, l, r);
pushup(t);
}
long long query(int t, int l, int r){
if(tree[t].l >= l && tree[t].r <= r){
return tree[t].summ % p;
}pushdown(t);
int mid = tree[t].l + tree[t].r >> 1;long long cnt = 0;
if(mid >= l)cnt = query(t + t, l, r);
if(mid < r)cnt += query(t + t + 1, l, r);
pushup(t);
return cnt % p;
}
int main(){
scanf("%d%d", &n, &p);
build(1, n, 1);
int m; scanf("%d", &m); while(m --){
scanf("%d%d%d", &la, &a, &b);
if(la != 3){scanf("%d", &c);
alter(1, a, b);
}else{
printf("%lld\n", query(1, a, b));
}
}
return 0;
}
bzoj1500 维修数列
这道题要处理的东西有点多, 但实际上每一个小模块都是之前写过的, 只是把它们整合在一起而已。
易错点: 1, 在转移的时候要判左右儿子是否为空(我开始是想不去特判而给空的节点赋一个很小的值什么的, 但都不好实现)
2, 垃圾回收避免MLE。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define MAXN 510005
#define INF 1<<30
using namespace std;
int n, m, root, cnt, fat[MAXN], ch[MAXN][2], sz[MAXN], summ[MAXN], lmax[MAXN], rmax[MAXN], maxx[MAXN], num[MAXN], a[MAXN];
bool rev[MAXN], change[MAXN];
queue<int>q;
void newnode(int &x, int fatt, int val){
if(!q.empty())x = q.front(), q.pop();
else x = ++ cnt;
fat[x] = fatt;
ch[x][0] = ch[x][1] = rev[x] = change[x] = 0;
sz[x] = 1;
summ[x] = lmax[x] = rmax[x] = maxx[x] = num[x] = val;
}
inline void pushdown(int x){
if(!x)return;
if(rev[x]){
rev[x] = 0;
if(ch[x][0])rev[ch[x][0]] ^= 1;
if(ch[x][1])rev[ch[x][1]] ^= 1;
swap(ch[x][0], ch[x][1]);
swap(lmax[x], rmax[x]);
}
if(change[x]){
change[x] = 0;
if(ch[x][0]){
change[ch[x][0]] = 1;
num[ch[x][0]] = num[x];
summ[ch[x][0]] = num[x] * sz[ch[x][0]];
rmax[ch[x][0]] = lmax[ch[x][0]] = maxx[ch[x][0]] = max(num[x], summ[ch[x][0]]);
}
if(ch[x][1]){
change[ch[x][1]] = 1;
num[ch[x][1]] = num[x];
summ[ch[x][1]] = num[x] * sz[ch[x][1]];
rmax[ch[x][1]] = lmax[ch[x][1]] = maxx[ch[x][1]] = max(num[x], summ[ch[x][1]]);
}
}
}
inline void pushup(int x){
if(!x)return;
pushdown(ch[x][0]), pushdown(ch[x][1]);
summ[x] = (ch[x][0] ? summ[ch[x][0]] : 0) + (ch[x][1] ? summ[ch[x][1]] : 0) + num[x];
sz[x] = (ch[x][0] ? sz[ch[x][0]] : 0) + (ch[x][1] ? sz[ch[x][1]] : 0) + 1;
lmax[x] = max(ch[x][0] ? lmax[ch[x][0]] : num[x], (ch[x][0] ? summ[ch[x][0]] : 0) + num[x] + max(0, ch[x][1] ? lmax[ch[x][1]] : 0));
rmax[x] = max(ch[x][1] ? rmax[ch[x][1]] : num[x], (ch[x][1] ? summ[ch[x][1]] : 0) + num[x] + max(0, ch[x][0] ? rmax[ch[x][0]] : 0));
maxx[x] = max(max(ch[x][0] ? maxx[ch[x][0]] : num[x], ch[x][1] ? maxx[ch[x][1]] : num[x]), max(0, ch[x][0] ? rmax[ch[x][0]] : 0) + max(0, ch[x][1] ? lmax[ch[x][1]] : 0) + num[x]);
}
void build(int &x, int l, int r, int fat){
if(l <= r){
int mid = l + r >> 1;
//cout<<mid<<endl;
//cout<<a[mid]<<endl;
newnode(x, fat, a[mid]);
if(l == r)return;
if(mid > l)build(ch[x][0], l, mid - 1, x);
build(ch[x][1], mid + 1, r, x);
pushup(x);
}
}
inline void jie(int x, int y, int k){if(y)ch[y][k] = x; fat[x] = y;}
inline void rotate(int x, int k){
int y = fat[x];pushdown(y);//pushdown(x);
jie(ch[x][k], y, !k);
jie(x, fat[y], ch[fat[y]][1] == y);
jie(y, x, k);
pushup(y);
}
void splay(int x, int goal){
if(x == goal)return;
pushdown(x);
while(fat[x] != goal){
if(fat[fat[x]] == goal){
// pushdown(fat[x]);
// pushdown(x);
rotate(x, ch[fat[x]][0] == x); break;
}
// pushdown(fat[fat[x]]);
// pushdown(fat[x]);
// pushdown(x);
int y = fat[x], ky = ch[fat[y]][1] == y;
if(ch[y][ky] == x)rotate(y, !ky), rotate(x, !ky);
else rotate(x, ky), rotate(x, !ky);
}pushup(x);
if(!goal)root = x;
}
int select(int k){
int x = root; pushdown(x);
while(sz[ch[x][0]] + 1 != k){
if(sz[ch[x][0]] + 1 < k){
k -= sz[ch[x][0]] + 1;
x = ch[x][1];
}
else x = ch[x][0];
pushdown(x);
}return x;
}
void Reverse(int a, int b){
int A = select(a), B = select(b + 2);
splay(A, 0), splay(B, A);
rev[ch[B][0]] ^= 1;
pushup(B), pushup(A);
}
int Get_sum(int a, int b){
int A = select(a), B = select(b + 2);
splay(A, 0), splay(B, A);
return summ[ch[B][0]];
}
void del(int x){
if(!x)return;
q.push(x);
del(ch[x][0]);
del(ch[x][1]);
}
void Delete(int a, int b){
int A = select(a), B = select(b + 2);
splay(A, 0), splay(B, A);
del(ch[B][0]);
ch[B][0] = 0;
pushup(B), pushup(A);
}
int Max_sum(){
int A = select(1), B = select(sz[root]);
splay(A, 0), splay(B, A);
return maxx[ch[B][0]];
}
void Make_same(int a, int b, int c){
int A = select(a), B = select(b + 2);
splay(A, 0), splay(B, A);
int x = ch[B][0];
change[x] = 1;
num[x] = c;
summ[x] = c * sz[x];
rmax[x] = lmax[x] = maxx[x] = max(c, summ[x]);
pushup(B), pushup(A);
}
void Insert(int a, int b){a ++;
int A = select(a), B = select(a + 1);
splay(A, 0), splay(B, A);
// printf("!! %d %d\n", summ[ch[ch[root][1]][0]], summ[root]);
build(ch[ch[root][1]][0], 1, b, ch[root][1]);
pushup(ch[root][1]); pushup(root);
// printf("!! %d %d\n", summ[ch[ch[root][1]][0]], summ[root]);
}
int main(){
// freopen("sequence.in", "r", stdin);
// freopen("sequence.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)scanf("%d", &a[i]);
newnode(root, 0, -10000);
newnode(ch[root][1], root, -10000);
sz[root] ++;
build(ch[ch[root][1]][0], 1, n, ch[root][1]);
pushup(ch[root][1]); pushup(root);
// for(int i = 1; i <= 15; i ++)printf("%d %d %d %d\n", i, num[i], lmax[i], maxx[i]);
char s[30]; int aa, bb, cc, dd, ee;
while(m --){scanf("%s", s); // cout<<"!!!!"<<endl;
// printf("!! %s", s);
if(s[0] == 'R'){
scanf("%d%d", &aa, &bb);
Reverse(aa, aa + bb - 1);
}
if(s[0] == 'G'){
scanf("%d%d", &aa, &bb);
// cout<<"######"<<endl;
printf("%d\n", Get_sum(aa, aa + bb - 1));
}
if(s[0] == 'D'){
scanf("%d%d", &aa, &bb); n -= bb;
Delete(aa, aa + bb - 1);
}
if(s[0] == 'M' && s[2] == 'X'){
// cout<<"!!!!"<<endl;
printf("%d\n", Max_sum());
}
if(s[0] == 'M' && s[2] == 'K'){
scanf("%d%d%d", &aa, &bb, &cc);
Make_same(aa, aa + bb - 1, cc);
}
if(s[0] == 'I'){
scanf("%d%d", &aa, &bb); n += bb;
for(int i = 1; i <= bb; i ++)scanf("%d", &a[i]);
Insert(aa, bb);
}
// printf("%d\n", Get_sum(1, n));
/* int pre; pre = 0;
for(int i = 1; i <= sz[root]; i ++){
splay(select(i), pre); pre = select(i);
}*/
// for(int i = sz[root]; i >= 1; i --)printf("%d %d %d %d\n", maxx[select(i)], ch[select(i)][0], ch[select(i)][1], num[select(i)]);
}
return 0;
}
bzoj 1208 宠物收养所
还是特别简单的一道裸题。
就是一个支持插入, 删除, 询问前驱和后继的splay。
我第一次在对 INF 操作的时候忘记了会爆int, 所以WA 了一次, 这种错误是在以后必须避免的。
12.11 : 我下面的这个代码虽然可以A但是是错的, 应该再 特判 要删除的那个节点是不是 在最开始建出来的虚点, 因为这是早年的题所以数据比较水。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define MAXN 80005
#define INF (1<<31) - 1
using namespace std;
int n, ans, flag = -1, fat[MAXN], ch[MAXN][2], root, a[MAXN], cntt, now;
inline void jie(int x, int y, int k){if(y)ch[y][k] = x; fat[x] = y;}
inline void rotate(int x, int k){
int y = fat[x];
jie(ch[x][k], y, !k), jie(x, fat[y], ch[fat[y]][1] == y), jie(y, x, k);
}
void splay(int x, int goal){if(x == goal)return;
while(fat[x] != goal){
if(fat[fat[x]] == goal){rotate(x, ch[fat[x]][0] == x); break; }
int y = fat[x], ky = ch[fat[y]][1] == y;
if(ch[y][ky] == x)rotate(y, !ky), rotate(x, !ky);
else rotate(x, ky), rotate(x, !ky);
} if(goal == 0)root = x;
}
void newnode(int &x, int ff, int c){
x = ++ cntt, a[cntt] = c, fat[cntt] = ff;
}
void insert(int x){
int r = root;
while(ch[r][a[r] < x])r = ch[r][a[r] < x];
newnode(ch[r][a[r] < x], r, x);
splay(cntt, 0);
}
int pre(int x){
int tmp = ch[x][0];if(!tmp)return 1;
while(ch[tmp][1])tmp = ch[tmp][1]; return tmp;
}
int hou(int x){
int tmp = ch[x][1];if(!tmp)return 2;
while(ch[tmp][0])tmp = ch[tmp][0]; return tmp;
}
void del(int x){
int pree = pre(x), houu = hou(x);
splay(pree, 0), splay(houu, root);
ch[houu][0] = 0;
}
void work(int x){
insert(x); splay(cntt, 0);
int pree = pre(cntt), houu = hou(cntt);
int tmp = abs((long long)a[pree] - x) <= abs((long long)a[houu] - x) ? pree : houu;
ans += abs(a[tmp] - x); ans %= 1000000;
del(root);//printf("%d %d\n", a[pree], a[houu]);
splay(tmp, 0); del(tmp);
}
int main(){
newnode(root, 0, INF + 1), newnode(ch[root][1], root, INF);
scanf("%d", &n);while(n --){
int k, c; scanf("%d%d", &k, &c);
if(flag == -1 || flag == k)insert(c), now ++, flag = k;
else work(c), now --;
if(!now)flag = -1;
}cout<<ans<<endl;
return 0;
}
bzoj 1507 editor