bzoj1251: 序列终结者 (splay)

splay可以用于维护序列,比如noi的维修序列,比如这道

发现当时splay没写总结,也没题解

然后重新写splay竟然耗了一个晚上

结果是因为max【0】没有附最小值!!血一样的教训

最后祭出inline大法才过,我的splay真的慢到吐血

{$inline on}
{$M 1000000000,0,maxlongint}
const
  //mm=maxlongint>>2;
  maxn=60000;

var
  size,left,right,mark,fa,value,max:array[0..maxn]of longint;
  rev:array[0..maxn]of boolean;
  root,i,j,k,l,n,m,tot,x:longint;

function new:longint;inline;
begin
  inc(tot);
  exit(tot);
end;

function mmax(x,y:longint):longint;inline;
begin
  if x<y then exit(y);
  exit(x)
end;

procedure swap(var x,y:longint);inline;
var
  i:longint;
begin
  i:=x;
  x:=y;
  y:=i;
end;

procedure pushdown(x:longint);inline;
begin
  if x=0 then exit;
  if rev[x] then begin
    swap(left[x],right[x]);
    rev[left[x]]:=rev[left[x]] xor true;
    rev[right[x]]:=rev[right[x]] xor true;
    rev[x]:=false;
  end;
  if mark[x]<>0 then begin
    value[x]:=value[x]+mark[x];
    max[x]:=max[x]+mark[x];
    inc(mark[left[x]],mark[x]);
    inc(mark[right[x]],mark[x]);
    mark[x]:=0;
  end;
end;

procedure update(x:longint);inline;
begin
  pushdown(x);
  pushdown(left[x]);
  pushdown(right[x]);
  size[x]:=size[left[x]]+size[right[x]]+1;
  max[x]:=mmax(value[x],mmax(max[left[x]],max[right[x]]));
end;

procedure lt(x:longint);inline;
var
  u,k:longint;
  flag:boolean;
begin
  pushdown(x);
  pushdown(right[x]);
  k:=right[x];
  u:=fa[x];
  if left[u]=x then flag:=true else flag:=false;
  right[x]:=left[k];
  fa[right[x]]:=x;
  left[k]:=x;
  fa[x]:=k;
  update(x);
  update(k);
  fa[k]:=u;
  if flag then left[u]:=k else right[u]:=k;
end;

procedure rt(x:longint);inline;
var
  u,k:longint;
  flag:boolean;
begin
  pushdown(x);
  pushdown(left[x]);
  k:=left[x];
  u:=fa[x];
  if left[u]=x then flag:=true else flag:=false;
  left[x]:=right[k];
  fa[left[x]]:=x;
  right[k]:=x;
  fa[x]:=k;
  update(x);
  update(k);
  fa[k]:=u;
  if flag then left[u]:=k else right[u]:=k;
end;

procedure splay(x,u:longint);inline;
begin
  while fa[x]<>u do begin
    if fa[fa[x]]=u then begin
      if left[fa[x]]=x then rt(fa[x])
        else lt(fa[x]);
      exit;
    end;
    if left[fa[x]]=x then begin
      if left[fa[fa[x]]]=fa[x] then rt(fa[fa[x]]);
      rt(fa[x]);
    end
    else begin
      if right[fa[fa[x]]]=fa[x] then lt(fa[fa[x]]);
      lt(fa[x]);
    end;
  end;
end;

function find(x,y:longint):longint;inline;
begin
  pushdown(x);
  if size[left[x]]=y-1 then exit(x);
  if y<=size[left[x]] then exit(find(left[x],y))
    else exit(find(right[x],y-1-size[left[x]]));
end;

function change(j,k:longint):longint;inline;
var
  now:longint;
begin
  now:=find(root,j);
  splay(now,0);
  root:=now;
  now:=find(root,k+2);
  splay(now,root);
  exit(now);
end;

function build(l,r:longint):longint;inline;
var
  mid,x:longint;
begin
  mid:=(l+r)>>1;
  x:=new;
  value[x]:=0;
  size[x]:=r-l+1;
  rev[x]:=false;
  mark[x]:=0;
  left[x]:=0;
  right[x]:=0;
  if l=r then begin
    if (l=0) or (l=n+1) then value[x]:=-maxlongint>>1;
    max[x]:=value[x];
    exit(x);
  end;
  if l<mid then begin
    left[x]:=build(l,mid-1);
    fa[left[x]]:=x;
  end;
  if mid<r then begin
    right[x]:=build(mid+1,r);
    fa[right[x]]:=x;
  end;
  update(x);
  exit(x);
end;

begin
  readln(n,m);
  max[0]:=-maxlongint;
  root:=build(0,n+1);
  while m>0 do begin
    dec(m);
    read(j);
    if j=1 then begin
      readln(j,k,l);
      x:=change(j,k);
      inc(mark[left[x]],l);
      update(x);
      update(root);
    end
    else
    if j=2 then begin
      readln(j,k);
      x:=change(j,k);
      rev[left[x]]:=rev[left[x]] xor true;
      update(x);
      update(root);
    end
    else begin
      readln(j,k);
      x:=change(j,k);
      writeln(max[left[x]]);
    end;
  end;
end.

splay还可以当普通的平衡树做?就是把旋转改为旋转为根?再找到题写吧。

时间: 2024-10-01 04:42:06

bzoj1251: 序列终结者 (splay)的相关文章

BZOJ1251&#183;序列终结者

好像不能附传送门了..这是道sb权限题.. 1251: 序列终结者 Time Limit: 20 Sec  Memory Limit: 162 MB Description 网 上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终

【bzoj1251】序列终结者 splay

序列终结者 Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧. [问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将[L,R]这个区间内的所有数

[BZOJ1251]序列终结者

试题描述 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量--这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个"库"可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧. [问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V. 2.

BZOJ 1251: 序列终结者( splay )

先orz一下clj...我的splay跟着他写的... 这道题很普通的splay我调了这么久 T T , 就是因为 null 的值初始化为0 , 结果就挂了... -------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream>

Bzoj 1251: 序列终结者 (Splay 模板题)

题面(太裸太裸,不看也罢) 就是维护一个区间加,区间翻转和区间最大值. 贴一个风格以后可以一直用 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 100000 6 #define XX getchar() 7 using namespace std; 8 int ch[N][2],fa[N],rev[N],ad[N],b

BZOJ 1251 序列终结者(Splay)

题目大意 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧.[问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将 [L, R] 这个区间内的所有数加上 V. 2. 将 [

【BZOJ】1251: 序列终结者(splay)

http://www.lydsy.com/JudgeOnline/problem.php?id=1251 不行..为什么写个splay老是犯逗,这次又是null的mx没有赋值-maxlongint... #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #inc

bzoj 1251: 序列终结者 2011-12-20

1251: 序列终结者Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 650  Solved: 277[Submit][Status][Discuss]Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可

【CodeVS4665】序列终结者

Description 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧. 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将[L,R]这个区间内的所有数加上V. 2. 将[L,R