及其简短的Splay代码

#include <stdio.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#define inf 1000000000
using namespace std;
#define getch() getchar()
inline int F() {register int aa , bb , ch;
    while(ch = getch() , (ch<‘0‘||ch>‘9‘) && ch != ‘-‘); ch == ‘-‘ ? aa=bb=0 : (aa=ch-‘0‘,bb=1);
    while(ch = getch() , ch>=‘0‘&&ch<=‘9‘) aa = aa*10 + ch-‘0‘; return bb ? aa : -aa;
}
const int Maxn = 1000005;
queue<int> q;
int n , m , root , sz;
int fa[Maxn] , c[Maxn][2] , mx[Maxn] , lx[Maxn] , rx[Maxn] , v[Maxn] , size[Maxn] , sum[Maxn] , a[Maxn] , id[Maxn];
bool lazy[Maxn] , rev[Maxn];

void update(int x) {
    int lc = c[x][0] , rc = c[x][1];
    sum[x] = sum[lc] + sum[rc] + v[x];
    size[x] = size[lc] + size[rc] + 1;
    mx[x] = max(mx[lc] , mx[rc]);
    mx[x] = max(mx[x] , rx[lc]+v[x]+lx[rc]);
    lx[x] = max(lx[lc] , sum[lc] + v[x] + lx[rc]);
    rx[x] = max(rx[rc] , sum[rc] + v[x] + rx[lc]);
}

void downpush(int x) {
    int lc = c[x][0] , rc = c[x][1];
    if(lazy[x]) {
        rev[x] = lazy[x] = 0;
        if(lc) lazy[lc] = 1 , v[lc] = v[x] , sum[lc] = v[x]*size[lc];
        if(rc) lazy[rc] = 1 , v[rc] = v[x] , sum[rc] = v[x]*size[rc];
        if(v[x] >= 0) {
            if(lc) lx[lc] = rx[lc] = mx[lc] = sum[lc];
            if(rc) lx[rc] = rx[rc] = mx[rc] = sum[rc];
        }
        else {
            if(lc) lx[lc] = rx[lc] = 0 , mx[lc] = v[x];
            if(rc) lx[rc] = rx[rc] = 0 , mx[rc] = v[x];
        }
    }
    if(rev[x]) {
        rev[x] = 0;
        rev[lc] ^= 1;
        rev[rc] ^= 1;
        swap(lx[lc] , rx[lc]);
        swap(lx[rc] , rx[rc]);
        c[x][0] = rc;
        c[x][1] = lc;
        swap(lx[x] , rx[x]);
    }
}

void rotate(int&root , int x) {
    int y = fa[x] , z = fa[y] , p , q;
    if(x == c[y][0]) p = 0; else p = 1;
    q = p^1;
    if(y == root) root = x;
    else {
        if(c[z][0] == y) c[z][0] = x;
        else c[z][1] = x;
    }
    fa[x] = z; fa[y] = x; fa[c[x][q]] = y;
    c[y][p] = c[x][q]; c[x][q] = y;
    update(y); update(x);
}
void splay(int&root , int x) {
    int y , z;
    while(x != root) {
        y = fa[x] , z = fa[y];
        if(y != root) {
            if((x == c[y][0]) ^ (y == c[z][0])) rotate(root , x);
            else rotate(root , y);
        }
        rotate(root , x);
    }
}

int find(int x , int rk) {
    downpush(x);
    int lc = c[x][0] , rc = c[x][1];
    if(size[lc] + 1 == rk) return x;
    if(size[lc] >= rk) return find(lc , rk);
    else return find(rc , rk-size[lc]-1);
}

void rec(int x) {
    if(!x) return ;
    int lc = c[x][0] , rc = c[x][1];
    rec(lc);rec(rc);q.push(x);
    fa[x] = c[x][0] = c[x][1] = lazy[x] = rev[x] = 0;
}

int split(int k , int tot) {
    int x = find(root , k);
    splay(root , x);
    x = find(root , k+tot+1);
    splay(c[root][1] , x);
    return c[ c[root][1] ][0];
}

void query(int k , int tot) {
    int x = split(k , tot);
    printf("%d\n",sum[x]);
}

void modify(int k , int tot , int val) {
    int x = split(k , tot) , y = fa[x];
    v[x] = val; lazy[x] = 1; sum[x] = size[x]*val;
    if(val >= 0) lx[x] = rx[x] = mx[x] = sum[x];
    else lx[x] = rx[x] = 0 , mx[x] = val;
    update(y); update(fa[y]);
}

void reverse(int k , int tot) {
    int x = split(k , tot);
    if(!lazy[x]) {
        rev[x] ^= 1;
        downpush(x);
        update(fa[x]);
        update(fa[fa[x]]);
    }
}

void erase(int k , int tot) {
    int x = split(k , tot) , y = fa[x];
    rec(x); c[y][0] = 0;
    update(y); update(fa[y]);
}
void build(int l,int r,int f)
{
    if(l>r)return;
    int mid=(l+r)>>1,now=id[mid],last=id[f];
    if(l==r)
    {
        sum[now]=a[l];size[now]=1;
        lazy[now]=rev[now]=0;
        if(a[l]>=0)lx[now]=rx[now]=mx[now]=a[l];
        else lx[now]=rx[now]=0,mx[now]=a[l];
    }
    else build(l,mid-1,mid),build(mid+1,r,mid);
    v[now]=a[mid];fa[now]=last;update(now);
    c[last][mid>=f]=now;
   }
void insert(int k,int tot)
{
    for(int i=1;i<=tot;i++)a[i]=F();
    for(int i=1;i<=tot;i++)
        if(!q.empty())id[i]=q.front(),q.pop();
        else id[i]=++sz;
    build(1,tot,0);int z=id[(1+tot)>>1];
    int x=find(root,k+1),y=find(root,k+2);
    splay(root,x);splay(c[x][1],y);
    fa[z]=y;c[y][0]=z;
    update(y);update(x);
}

int main() {
    n = F(); m = F();
    mx[0] = a[1] = a[n+2] = -inf;
    for(int i=1; i<=n; ++i) {
        a[i+1] = F();
    }
    for(int i=1;i<=n+2;i++)id[i]=i;
    build(1,n+2,0);
    root = (n+3) >> 1;sz = n + 2;
    int k , tot , val;
    char ch[10];
    while(m--) {
        scanf("%s",ch);
        if(ch[0]!=‘M‘ || ch[2] != ‘X‘) k = F() , tot = F();
        if(ch[0] == ‘I‘) insert(k , tot);
        if(ch[0] == ‘D‘) erase(k , tot);
        if(ch[0] == ‘M‘) {
            if(ch[2] == ‘X‘) printf("%d\n",mx[root]);
            else val = F() , modify(k , tot , val);
        }
        if(ch[0] == ‘R‘) reverse(k , tot);
        if(ch[0] == ‘G‘) query(k , tot);
    }
}

Splay的核心操作

void rotate(int&root , int x) {
    int y = fa[x] , z = fa[y] , p , q;
    if(x == c[y][0]) p = 0; else p = 1;
    q = p^1;
    if(y == root) root = x;
    else {
        if(c[z][0] == y) c[z][0] = x;
        else c[z][1] = x;
    }
    fa[x] = z; fa[y] = x; fa[c[x][q]] = y;
    c[y][p] = c[x][q]; c[x][q] = y;
    update(y); update(x);
}
void splay(int&root , int x) {
    int y , z;
    while(x != root) {
        y = fa[x] , z = fa[y];
        if(y != root) {
            if((x == c[y][0]) ^ (y == c[z][0])) rotate(root , x);
            else rotate(root , y);
        }
        rotate(root , x);
    }
}
时间: 2024-10-29 00:59:14

及其简短的Splay代码的相关文章

一个 11 行 Python 代码实现的神经网络

概要:直接上代码是最有效的学习方式.这篇教程通过由一段简短的 python 代码实现的非常简单的实例来讲解 BP 反向传播算法. 代码如下: Python 1 2 3 4 5 6 7 8 9 10 11 X = np.array([ [0,0,1],[0,1,1],[1,0,1],[1,1,1] ]) y = np.array([[0,1,1,0]]).T syn0 = 2*np.random.random((3,4)) - 1 syn1 = 2*np.random.random((4,1))

codevs 1743 反转卡片 rope or splay

[codevs1743]反转卡片 题目描述 Description [dzy493941464|yywyzdzr原创] 小A将N张卡片整齐地排成一排,其中每张卡片上写了1~N的一个整数,每张卡片上的数各不相同. 比如下图是N=5的一种情况:3 4 2 1 5 接下来你需要按小A的要求反转卡片,使得左数第一张卡片上的数字是1.操作方法:令左数第一张卡片上的数是K,如果K=1则停止操作,否则将左数第1~K张卡片反转. 第一次(K=3)反转后得到:2 4 3 1 5 第二次(K=2)反转后得到:4 2

PHP 代码规范、流程规范、git规范

代码规范.git规范.teambition规范.yii规范 1. 命名规范 (1).变量命名规范 1.变量使用驼峰命名法 禁止使用拼音或者拼音加数字 2.变量也应具有描述性,杜绝一切拼音.或拼音英文混杂的命名方式 3.变量包数字.字母和下划线字符,不允许使用其他字符,变量命名最好使用项目 中有据可查的英文缩写方式, 尽可以要使用一目了然容易理解的形式: 4.变量以字母开头,如果变量包多个单词,首字母小写,当包多个单词时,后面 的每个单词的首字母大写. 例如 :$itSports 5.变量使用有效

iOS高仿微信完整源码,网易爱玩APP源码等

iOS精选源码 iOS一种弹出视图效果带动画 一个快速便捷.无侵入.可扩展的动画弹框库 高仿Elk - 旅行货币转换器 iOS内分享的界面.功能一体化解决方案 使用Olami sdk实现一个语音查询股票的iOS程序 iOS高仿微信完整项目源码 分段绘制折线指示图, 点击效果 最新环信推送封装 v3.0[附代码] 仿照网易爱玩APP APP启动视频 iOS优质博客 iOS 一行代码搞定 KVO 前言发现好久没有研究.学习iOS优秀开源代码,现在大部分时间都在写业务代码, 学习其他语言及一些杂七杂八

Tyvj 1729 文艺平衡树

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 4604  Solved: 2691[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作

【转】 C++ vector用法

在c++中,vector是一个十分有用的容器,下面对这个容器做一下总结. 1 基本操作 (1)头文件#include<vector>. (2)创建vector对象,vector<int> vec; (3)尾部插入数字:vec.push_back(a); (4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的. (5)使用迭代器访问元素. vector<int>::iterator it; for(it=vec.begi

python爬虫总结

主要涉及的库 requests 处理网络请求 logging 日志记录 threading 多线程 Queue 用于线程池的实现 argparse shell参数解析 sqlite3 sqlite数据库 BeautifulSoup html页面解析 urlparse 对链接的处理 关于requests 我没有选择使用python的标准库urllib2,urllib2不易于代码维护,修改起来麻烦,而且不易扩展, 总体来说,requests就是简单易用,如requests的介绍所说: built f

Excel图表编程应用大全(2):图表编程基础

嵌入式图表和图表工作表图表在工作表中有两种存在方式: 嵌入式图表与工作表的数据在一起,或者与其他的嵌入式图表在一起. 图表工作表是特定的工作表,只包含单独的图表. (1)嵌入式图表当希望图表作为工作表的一部分,与数据或其他图表在一起时,嵌入式图表是最好的选择.Chart对象代表每一个嵌入式图表,包含在ChartObject对象里.每个Excel工作表都有一个ChartObjects集合,包含工作表中每个嵌入式图表.为了在工作表中添加新的嵌入式图表,在集合中添加ChartObject对象,其语法为

使用lambda表达式操作HashMap

Java8之前,如果想根据map的value值来排序话,比较繁琐参看<如何将HashMap,按照value值排序 > 现在借助于lambda表达式,就方便多了. <span style="font-size:14px;">Map<String,Integer> map=new HashMap<>(); map.put("derek",24 ); map.put("dad", 51); map.put