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. MongoDb 2.4 beta新特性——全文索引

    期待已久的特性,但目前仍然在beta阶段,所以官方建议不要在生产环境使用.也因此需要手动打开这个特性. 在命令行指定 mongod --setParameter textSearchEnabled=t ...

  2. (转)Android如何编程设置APP安装位置(外部存储或内部存储)?

    Beginning with API Level 8, you can allow your application to be installed on the external storage ( ...

  3. 最新hosts,更新hosts,可用

    点击这里,全选后复制,粘贴到C:\Windows\System32\drivers\etc的hosts里面,把原来的置换了

  4. WinSock编程基础

    一.套接字模式   1.阻塞模式       创建套接字时,默认是阻塞模式,对recv函数调用会使程序进入等待状态,知道接收到数据才返回.   2.非阻塞模式:      可以调用ioctlsocke ...

  5. 小木棍 (codevs 3498)题解

    [问题描述] 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过100. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长 ...

  6. jquery的异步获取返回值为中文时乱码解决方法

    用jqgrid异步获取列表值,遇到个问题,服务器端从数据库取到的数据没有出现中文乱码问题(日志打出来是没有乱码的),但是异步传到客户的时候却出现了乱码. 服务器端已经编码过了(UTF-8编码).开始一 ...

  7. spring 中的两个DaoSupport类的使用对比

    可以利用NamedParameterJdbcDaoSupport 已经封装的NamedParameterJdbcTemplate方便的进行sql中参数的初始化工作. 相对于JdbcDaoSupport ...

  8. GestureDetector.OnGestureListener

    为了加强鼠标响应事件,Android提供了GestureDetector手势识别类.通过GestureDetector.OnGestureListener来获取当前被触发的操作手势(Single Ta ...

  9. ios中用drawRect方法绘图的时候设置颜色

    设置画笔颜色可以直接 [[UIColor grayColor] set];就可以设置颜色.

  10. Labview实现字符串加密

    Labview实现字符串加密 对字符串进行加密,规则是每个字母后移5 位 例如A 变为F,b 变为g,x 变为c,y 变为d- 实现效果 后端实现