splay

这个星期打了一些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的理解。


hdu1754 I hate it

这道题相信没人 没有用线段树做过, 因为什么操作都没有所以用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;
}


bzoj 1588 营业额统计

所以这次又新增了一个插入操作。

#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;
}


bzoj1503 郁闷的出纳员

所以这次又新增了删除操作。

#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;    
} 

bzoj1798 维护序列

这时候有了修改操作, 自然要用到懒标记, 懒标记的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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值