AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1500

[前言]

  据说没打这题就相当于没打过Splay,这题简直就是让你内心崩溃的...

  这题是一道综合味很强的题,初学者不要贸然尝试...先做些简单一点的[跟着笔者的步伐走...做一做3224、3223、1251、1014这种类型],最好也要有一定的线段树lazy_tag基础。

[分析]

  首先数据范围没写...但是前人告诉你必须要用Splay[写在source里了]

  所以说这题肯定有一个很大的数据范围...

  而这题中需要支持的操作大多是区间上的操作,也是有很多下传标记和求区间和与区间最值的,同时有翻转操作[似乎支持这些的也只有伸展树了...]。

  确定了总的方向,再具体看看操作:

  1.预处理出一开始给你的数列。[和平常一样构造就好,这个部分最需要注意的就是下标这种细节了]

  2.在一个位置后添加一段序列,和以前加一个数字的操作很像,但是我们要像之前处理初始序列一样将这棵子树先构造出来,再将根接到位置上。

  3.删除一段序列,以往的题,只需要将这棵子树与父节点的关系弄掉即可,这题因为点数要求多[每次删一段,加一段],所以还需要回收这些删除的点,具体方法[暴力一个个点的下去,把他们的编号放进墓地里]。

  4.修改一段序列为一个定值,和线段树的强制赋值一样处理就好了。

  5.翻转一段区间,翻转标记的处理,具体见BZOJ3223。

  6.求一段区间的和,每次上传的时候需要更新一下。

  7.求全局中的最大子串,这个稍稍难想一点。

  同样的因为上面的这种设置方法,我们在进行翻转操作的时候记得也要翻转lmax,rmax

  当然具体的细节问题,给你们自己去调试咯...

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm> using namespace std; inline int in(){
int x=,f=;char ch=getchar();
while((ch>'' || ch<'') && ch!='-') ch=getchar();
if(ch=='-') f=-,ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return x*f;
} const int maxn=;
const int INF=0x3f3f3f3f; struct Node{
int ch[],f; //child[2],father
int sz,dt,sm; //size,data,sum
int lx,rx,mx; //left_max,right_max,Max bool rv,pt; //rev,paint
}s[maxn]; int n,q,rt,tot1;
int st[maxn],tot2;//墓地和容量
int a[maxn];
char ch[]; void NewNode(int &r,int father,int k){
if(tot2) r=st[tot2--];//优先选择墓地里的
else r=++tot1;
s[r].f=father;
s[r].ch[]=s[r].ch[]=;
s[r].dt=s[r].sm=k;
s[r].rv=s[r].pt=;
s[r].lx=s[r].rx=s[r].mx=k;
s[r].sz=;
} //应用并下传rev标记,记得要旋转左右最值
void Update_Rev(int x){
if(!x) return;
swap(s[x].ch[],s[x].ch[]);
swap(s[x].lx,s[x].rx);
s[x].rv^=;
} //应用并下传paint标记
void Update_Same(int x,int v){
if(!x) return;
s[x].dt=v;
s[x].sm=v*s[x].sz;
s[x].lx=s[x].rx=s[x].mx=max(v,v*s[x].sz);
s[x].pt=;
} //更新节点信息
void push_up(int x){
int l=s[x].ch[],r=s[x].ch[];
s[x].sz=s[l].sz+s[r].sz+;
s[x].sm=s[l].sm+s[r].sm+s[x].dt;
s[x].lx=max(s[l].lx,s[l].sm+s[x].dt+max(,s[r].lx));
s[x].rx=max(s[r].rx,s[r].sm+s[x].dt+max(,s[l].rx));
s[x].mx=max(,s[l].rx)+s[x].dt+max(,s[r].lx);
s[x].mx=max(s[x].mx,max(s[l].mx,s[r].mx));
} void push_down(int x){
if(s[x].pt){
Update_Same(s[x].ch[],s[x].dt);
Update_Same(s[x].ch[],s[x].dt);
s[x].pt=;
}
if(s[x].rv){
Update_Rev(s[x].ch[]);
Update_Rev(s[x].ch[]);
s[x].rv=;
}
} void Build(int &x,int l,int r,int father){
if(l>r) return;
int mid=(l+r)>>;
NewNode(x,father,a[mid]);
Build(s[x].ch[],l,mid-,x);
Build(s[x].ch[],mid+,r,x);
push_up(x);
} void Init(){
rt=tot1=tot2=;
s[rt].ch[]=s[rt].ch[]=s[rt].sz=s[rt].f=;
s[rt].pt=s[rt].rv=s[rt].sm=s[rt].dt=;
s[rt].lx=s[rt].rx=s[rt].mx=-INF;
NewNode(rt,,-);
NewNode(s[rt].ch[],rt,-);
for(int i=;i<n;i++)
scanf("%d",&a[i]);
Build(s[s[rt].ch[]].ch[],,n-,s[rt].ch[]);
push_up(s[rt].ch[]);
push_up(rt);
} void Rotate(int x,int k){
int y=s[x].f;
s[x].f=s[y].f;
if(s[y].f){
if(y==s[s[y].f].ch[])
s[s[y].f].ch[]=x;
else
s[s[y].f].ch[]=x;
}
s[y].ch[k]=s[x].ch[k^];
if(s[x].ch[k^]) s[s[x].ch[k^]].f=y;
s[x].ch[k^]=y;s[y].f=x;
push_up(y),push_up(x);
} void Splay(int x,int gf){
int y;
while(s[x].f!=gf){
y=s[x].f;
if(s[y].f==gf){
if(x==s[y].ch[]) Rotate(x,); else Rotate(x,);}
else{
int z=s[y].f;
if(y==s[z].ch[]){
if(x==s[y].ch[]) Rotate(y,),Rotate(x,); else Rotate(x,),Rotate(x,);}
else{
if(x==s[y].ch[]) Rotate(y,),Rotate(x,); else Rotate(x,),Rotate(x,);}
}
}
if(!gf) rt=x;
} int Get_kth(int k){
int p=rt;
while(p){
push_down(p);
if(k<=s[s[p].ch[]].sz) p=s[p].ch[];
else{
k-=s[s[p].ch[]].sz;
if(k==) return p;
k--;p=s[p].ch[];
}
}
} //在第pos个数后面插入tot个数
void Insert(int pos,int tot){
for(int i=;i<tot;i++) scanf("%d",&a[i]);
int x1=Get_kth(pos+),x2=Get_kth(pos+);
Splay(x1,),Splay(x2,x1);
Build(s[x2].ch[],,tot-,x2);
push_up(x2),push_up(x1);
} //删除子树
void erase(int x){
if(!x) return; st[++tot2]=x;//删除的节点需要回收进墓地
erase(s[x].ch[]),erase(s[x].ch[]);
} //从第pos个数开始连续删除tot个数
void Delete(int pos,int tot){
int x1=Get_kth(pos),x2=Get_kth(pos+tot+);
Splay(x1,),Splay(x2,x1);
erase(s[x2].ch[]);
s[s[x2].ch[]].f=;
s[x2].ch[]=;
push_up(x2),push_up(x1);
} //将从第pos个数开始的连续的tot个数染色成c
void Make_Same(int pos,int tot,int c){
int x1=Get_kth(pos),x2=Get_kth(pos+tot+);
Splay(x1,),Splay(x2,x1);
Update_Same(s[x2].ch[],c);
push_up(x2),push_up(x1);
} //将第pos个数开始的连续tot个数进行反转
void Reverse(int pos,int tot){
int x1=Get_kth(pos),x2=Get_kth(pos+tot+);
Splay(x1,),Splay(x2,x1);
Update_Rev(s[x2].ch[]);
push_up(x2),push_up(x1);
} //得到第pos个数开始的tot个数的和
int Get_Sum(int pos,int tot){
int x1=Get_kth(pos),x2=Get_kth(pos+tot+);
Splay(x1,),Splay(x2,x1);
return s[s[x2].ch[]].sm;
} //得到第pos个数开始的tot个数中最大的子段和
int Get_MaxSum(int pos,int tot){
int x1=Get_kth(pos),x2=Get_kth(pos+tot+);
Splay(x1,),Splay(x2,x1);
return s[s[x2].ch[]].mx;
} int main(){
#ifndef ONLINE_JUDGE
freopen("1500.in","r",stdin);
freopen("1500.out","w",stdout);
#endif
int L,tot,x; n=in();q=in();
Init();
while(q--){
scanf("%s",ch);
if(ch[]=='I')
L=in(),tot=in(),Insert(L,tot);
else if(ch[]=='D')
L=in(),tot=in(),Delete(L,tot);
else if(ch[]=='M'){
if(ch[]=='K')
L=in(),tot=in(),x=in(),Make_Same(L,tot,x);
else
printf("%d\n",Get_MaxSum(,s[rt].sz-));
}
else if(ch[]=='R')
L=in(),tot=in(),Reverse(L,tot);
else
L=in(),tot=in(),printf("%d\n",Get_Sum(L,tot));
}
return ;
}

BZOJ1500 维修数列的更多相关文章

  1. [bzoj1269]文本编辑器editor [bzoj1500]维修数列

    1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2540 Solved: 923 [Submit ...

  2. [bzoj1500 维修数列](NOI2005) (splay)

    真的是太弱了TAT...光是把代码码出来就花了3h..还调了快1h才弄完T_T 号称考你会不会splay(当然通过条件是1h内AC..吓傻)... 黄学长的题解:http://hzwer.com/28 ...

  3. [BZOJ1500][NOI2005]维修数列---解题报告

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

  4. 【BZOJ1500】【NOI2005】维修数列(Splay)

    [BZOJ1500][NOI2005]维修数列(Splay) 题面 不想再看见这种毒瘤题,自己去BZOJ看 题解 Splay良心模板题 真的很简单 我一言不发 #include<iostream ...

  5. [BZOJ1500][NOI2005]维修数列 解题报告 Splay

    Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...

  6. 【BZOJ1500】[NOI2005]维修数列 Splay

    [BZOJ1500][NOI2005]维修数列 Description Input 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目.第2行 ...

  7. [bzoj1500][NOI2005]维修数列_非旋转Treap

    维修数列 bzoj-1500 NOI-2005 题目大意:给定n个数,m个操作,支持:在指定位置插入一段数:删除一个数:区间修改:区间翻转.查询:区间和:全局最大子序列. 注释:$1\le n_{ma ...

  8. 【BZOJ-1500】维修数列 Splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 11047  Solved: 3460[Submit][Statu ...

  9. bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1.覆盖标记用INF表示无覆盖标记,要求可能用0覆盖 2.代表空节点的0号节点和首尾的两个虚拟 ...

随机推荐

  1. ES6还是ES2015?

    遇到了一个困惑   原来称作es6的现在突然变成es2015 了 原因是这个事ecma-262 的第六次变更,所有以前按照惯例称为es6. 但是为了更小版本频繁发布,现在 标准叫法是:  esmasc ...

  2. MYSQL的存储引擎一般只要哪些?

    根据个人个人见解: MySQL的存储引擎(构成.安全.锁) Myisam:数据操作快速的一种引擎,支持全文检索.文件保存在数据库名称为目录名的 目录中,有3个文件,分别是表定义文件(.frm).数据文 ...

  3. mysql事件调度器定时删除binlog

    MySQL5.1.6起Mysql增加了事件调度器(Event Scheduler),可以用做定时执行某些特定任务,来取代原先只能由Linux操作系统的计划任务来执行的工作MySQL的事件调度器可以精确 ...

  4. 写一个函数,尽可能高效的,从一个标准 url 里取出文件的扩展名

    例如: http://www.sina.com.cn/abc/de/fg.php?id=1 需要取出 php 或 .php function getExt($url){ $arr=parse_url( ...

  5. 淘宝:OceanBase分布式系统负载均衡案例分享

    Heroku因"随机调度+Rails单线程处理导致延迟增加的负载均衡失败"的案例之后,我们在思考:在负载均衡测试时发现问题并妥善解决的成功经验有没有?于是,挖掘出"淘宝在 ...

  6. python 类属性和实例属性

    class AAA(): aaa = 10 # 情形1 obj1 = AAA() obj2 = AAA() print obj1.aaa, obj2.aaa, AAA.aaa # 情形2 obj1.a ...

  7. [转]从普通DLL中导出C++类 – dllexport和dllimport的使用方法(中英对照、附注解)

      这几天写几个小程序练手,在准备将一个类导出时,发现还真不知道如果不用MFC的扩展DLL,是怎么导出的.但我知道dllexport可以导出函数和变量,而且MFC扩展DLL就算是使用了MFC的功能,但 ...

  8. Oracle redo 日志切换时间频率

    DB: 11.2.0.3.0 查看Oracle的redo日志切换频率 两条SQL,原理是一样的,第二个用到了统计函数 时间单位:分钟 方法一. select * from v$log a where ...

  9. sql server 2016 management studio没有的解决方式

    最近安装sql sever2016后发现没有 management studio管理工具,无法操作sql server,可以单独下载安装后即可. 下载地址: https://msdn.microsof ...

  10. OpenStack:安装Neutron与provider network

    1. 安装(1)Install Networking services on a dedicated network node# apt-get install neutron-server neut ...