cogs 347 地震 splay

链接:http://cogs.pro/cogs/problem/problem.php?pid=347

题意:不断维护一个区间,要求支持的操作有:删除区间、插入区间、区间加减、查询区间最大值。

看到这个题我们直接想到splay。还是熟悉的老方法,事先建两个节点,每一次操作,不管属于任何一种操作,先将区间的右端点转到右儿子,左端点转到根节点3号孙子,即右儿子的左儿子处。

1、区间加减:直接修改,延迟标记。

2、区间删除:直接扔掉左边界对应节点即可。

3、查询:基本操作。

4、插入区间:首先找到该区间位置,然后用初始建树相同方法插入即可。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<vector>
  5 #define lch ch[0]
  6 #define rch ch[1]
  7 #define kch ch[k]
  8 #define xch ch[k^1]
  9 using namespace std;
 10 inline int read()
 11 {    char c=getchar();int x=0,y=1;
 12     while(c<‘0‘||c>‘9‘){if(c==‘-‘) y=-1;c=getchar();}
 13     while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
 14     return x*y;
 15 }
 16 int inf=0x7fffffff,n,q;
 17 class splay
 18 {    private:
 19         struct node
 20         {    int k,s,h,lazy;
 21             node* pt,*ch[2];
 22             node(const int& key)
 23             {    this->k=key;this->s=1;this->lazy=0;
 24                 this->lch=NULL;this->rch=NULL;
 25             }
 26             inline int sz(){return this?this->s:0;}
 27             inline int key(){return this?this->k:0;}
 28             inline int qh(){return this?this->h:-inf;}
 29             ~node()
 30             {    if(this->lch) delete this->lch;
 31                 if(this->rch) delete this->rch;
 32             }
 33             inline void mt()
 34             {    if(this) this->s=this->lch->sz()+this->rch->sz()+1;
 35                 if(this) this->h=std::max(this->k,max(this->lch->qh(),this->rch->qh()));
 36             }
 37             inline void dn()
 38             {    if(this&&this->lazy)
 39                 {    if(lch) lch->lazy+=lazy,lch->k+=lazy,lch->h+=lazy;
 40                     if(rch) rch->lazy+=lazy,rch->k+=lazy,rch->h+=lazy;
 41                     lazy=0;
 42                 }
 43             }
 44             inline void Ad(int key){if(this){this->lazy+=key;this->k+=key;this->h+=key;}}
 45             inline int pos(){return this==this->pt->lch;}
 46         }*root;
 47         void rotate(node* rt,int k)
 48         {    node* tmp=rt->xch;
 49             rt->dn();tmp->dn();
 50             tmp->pt=rt->pt;
 51             if(!rt->pt) this->root=tmp;
 52             else if(rt->pt->lch==rt) rt->pt->lch=tmp;
 53             else rt->pt->rch=tmp;
 54             rt->xch=tmp->kch;
 55             if(tmp->kch) tmp->kch->pt=rt;
 56             tmp->kch=rt;rt->pt=tmp;
 57             rt->mt();tmp->mt();
 58         }
 59         void sp(node* rt,node* prt=NULL)
 60         {    while(rt->pt!=prt)
 61             {    int k=rt->pt->lch==rt;
 62                 if(rt->pt->pt==prt) rotate(rt->pt,k);
 63                 else
 64                 {    int d=rt->pt->pt->lch==rt->pt;
 65                     rotate(k==d?rt->pt->pt:rt->pt,k);
 66                     rotate(rt->pt,d);
 67                 }
 68             }
 69         }
 70         node* build(const std::vector<int>& v,int l,int r)
 71         {    if(l>r) return NULL;
 72             int mid=(l+r)>>1;node* tmp=new node(v[mid]);
 73             tmp->lch=build(v,l,mid-1);tmp->rch=build(v,mid+1,r);
 74             if(tmp->lch) tmp->lch->pt=tmp; if(tmp->rch) tmp->rch->pt=tmp;
 75             tmp->mt();
 76             return tmp;
 77         }
 78     public:
 79         ~splay(){delete this->root;}
 80         splay(const std::vector<int>& v){this->root=build(v,0,v.size()-1);}
 81         splay(){this->root=new node(-inf);this->root->rch=new node(-inf);this->root->rch->pt=this->root;}
 82         node* kth(int x)
 83         {    ++x;
 84             node* now=this->root;
 85             while(now!=NULL)
 86             {    now->dn();
 87                 int k=now->lch->sz()+1;
 88                 if(x<k) now=now->lch;
 89                 else if(x==k) return now;
 90                 else x-=k,now=now->rch;
 91             }
 92             return NULL;
 93         }
 94         void add(int x,int y,int z)
 95         {    node* tmp=this->kth(y+1),*tmp2=this->kth(x-1);
 96             this->sp(tmp2);this->sp(tmp,this->root);
 97             this->root->rch->lch->Ad(z);
 98             this->root->rch->mt();this->root->mt();
 99         }
100         void del(int x,int y)
101         {    node* tmp=this->kth(y+1),*tmp2=this->kth(x-1);
102             this->sp(tmp2);this->sp(tmp,this->root);
103             delete this->root->rch->lch;
104             this->root->rch->lch=NULL;
105             this->root->rch->mt();this->root->mt();
106         }
107         int hmax(int x,int y)
108         {    node* tmp=this->kth(y+1),*tmp2=this->kth(x-1);
109             this->sp(tmp2);this->sp(tmp,this->root);
110             return this->root->rch->lch->h;
111         }
112         void insert(int x,splay* data)
113         {    this->sp(this->kth(x));this->sp(this->kth(x+1),this->root);
114             node* tmp=data->root;data->root=NULL;
115             this->root->rch->lch=tmp;tmp->pt=this->root->rch;
116             this->root->rch->mt();this->root->mt();
117         }
118 };
119 int main()
120 {    freopen("equake.in","r",stdin);
121     freopen("equake.out","w",stdout);
122     n=read();q=read();
123     splay* tree=new splay();
124     std::vector<int>v;char ord[10];int x,y,z;
125     for(int i=1;i<=n;i++) v.push_back(read());
126     tree->insert(0,new splay(v));
127     for(int i=1;i<=q;i++)
128     {    scanf("%s",ord);
129         if(ord[0]==‘R‘){x=read();y=read();z=read();tree->add(x,y,z);}
130         if(ord[0]==‘I‘)
131         {    v.clear();x=read();y=read();
132             while(y--) v.push_back(read());
133             tree->insert(x,new splay(v));
134         }
135         if(ord[0]==‘M‘){x=read();y=read();tree->del(x,y);}
136         if(ord[0]==‘Q‘){x=read();y=read();printf("%d\n",tree->hmax(x,y));}
137     }
138     return 0;
139 }

cogs347

时间: 2024-10-06 12:10:32

cogs 347 地震 splay的相关文章

[COGS 347]地震

时间限制:4 s   内存限制:128 MB 问题描述 某国地形狭长,中部有一列山脉,由于多发地震,山脉在不断变化中.地震发生时,山脉有可能发生如下变化:局部海拔升高或降低,板块运动产生地裂而出现一段新的山脉,或板块挤压迫使一段山脉消失. 该国的科学考察队已经预测出了近期内将要发生的一次地震的全过程,他们得到的山脉变化的信息数据格式如下. R a b c a,b,c为三个整数,表示[a,b]这段山脉的海拔升高了c(或降低了-c). I a k t1 t2 ... tk a,k,t1,t2,...

COGS 74. [NOIP2006] 明明的随机数 (Splay小练习。。)

☆   输入文件:random.in   输出文件:random.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述]    明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1 到 1000 之间的随机整数( N ≤ 100 ),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号.然后再把这些数从小到大排序,按 照 排好的顺序去找同学做调查.请你协助明明完成“去重”与“排序”的工作. [输入格式]

数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

339. [NOI2005] 维护数列 ★★★★☆   输入文件:seq2005.in   输出文件:seq2005.out   简单对比 时间限制:3 s   内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1.  插入 INSERT_posi_tot_c1_c2_..._ctot 在当前数列的第 posi 个数字后插入 tot 个数字:c1, c2,

[模板]洛谷T2042 NOI2005 维护数列 Splay

PS:某大佬讲,当心情特别好or特别不好的时候,可以来攻略这个题...果然萌新足足被这题恶心了半个月... 进入正题: 这道题题意如此之裸-Splayの究极进化,那么就没有什么好讲的,直接说搞法好了... 为了代码写起来方便,萌新封装得可能有些过,若不合诸位大佬的口味还请见谅~ 节点node结构体定义: key:节点原值:size:子树大小:ch[2]:子树指针: set_pd:记录是否打了MAKE-SAME的懒标记:setv:MAKE-SAME的修改值:turn:记录是否旋转: sum:子树元

●Splay的一些题

●个人感觉: 代码长: 函数多: (很套路): (很强的Splay,无愧于"区间王") ●NOI2005维修数列 一个可以当模板学习的题,包含了众多操作(函数): 区间插入,删除,更新,翻转,询问信息以及"回收空间"(名字很刚)等. update()pushdown() rotate() splay() build() find() split() insert() rec() erase() query() rever() modify()还有main() 建议初

COGS 1715 &amp; bzoj 3295 [CQOI2011]动态逆序对 题解

(又是一道树套树……自己真是玩疯了……) (题意略) 从网上也看过题解,好像解法很多……比如CDQ+树状数组,树状数组套主席树,树状数组套平衡树……我用的是树状数组套splay. (我会说是因为我不会写CDQ和树状数组套主席树么= =) (不得不吐槽,为啥splay这么快= =) 也没啥可说的,我写的是在线算法,只要在删除一个元素之前统计它前面比它大的数和后面比它小的数的个数(区间求和用树状数组,统计比它小/大的数的个数用平衡树写),把答案减掉对应数值即可. 鉴于这题卡常,我就加了快读和各种in

BST, AVL Tree 和 Splay Tree 的实现

一.定义. 1.1 BST 二叉搜索树,也称有序二叉树,排序二叉树,是指一棵空树或者具有下列性质的二叉树: ① 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值: ② 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值: ③ 任意节点的左.右子树也分别为二叉查找树. ④ 没有键值相等的节点. 1.2 AVL Tree 平衡二叉树定义(AVL):它或者是一颗空树,或者具有以下性质的二叉树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子

HDU 2189 悼念512汶川大地震遇难同胞——来生一起走(母函数或完全背包)

悼念512汶川大地震遇难同胞--来生一起走 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3773    Accepted Submission(s): 1913 Problem Description 妈妈你别哭泪光照亮不了我们的路让我们自己慢慢的走 妈妈我会记住你和爸爸的模样记住我们的约定来生一起走 上面这首诗节选自一位诗人纪念遇难

BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

[题目分析] 模板题目. 首尾两个虚拟结点,十分方便操作. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #include