1500: [NOI2005]维修数列

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 6556  Solved: 1963
[Submit][Status]

Description

Input

输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。

Output

对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。

Sample Input

9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

Sample Output

-1
10
1
10

HINT

splay的難點就在於信息的同步與下放。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<string>
#include<queue>
using namespace std;
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#define MAXN 1100000
#define MAXV MAXN*2
#define MAXE MAXV*2
#define MAXT MAXN
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
typedef long long qword;
inline int nextInt()
{
char ch;
int x=;
bool flag=false;
do
ch=(char)getchar(),flag=(ch=='-')?true:flag;
while(ch<''||ch>'');
do x=x*+ch-'';
while (ch=(char)getchar(),ch<='' && ch>='');
return x*(flag?-:);
} int n,m;
struct Splay_tree
{
int ch[MAXT][];
int pnt[MAXT];
int val[MAXT];
int siz[MAXT];
int sum[MAXT];
int lx[MAXT],rx[MAXT],mx[MAXT];
int chgf[MAXT],rev[MAXT];
int stack[MAXT],tops;
int root;
queue<int> Q;
Splay_tree()
{
root=;
for (int i=;i<=;i++)
Q.push(i);
}
int nextNode()//支持垃圾回收機制
{
int now=Q.front();
Q.pop();
if (ch[now][])
Q.push(ch[now][]);
if (ch[now][])
Q.push(ch[now][]);
ch[now][]=ch[now][]=;
return now;
}
void Rotate(int now)
{
int p=pnt[now],anc=pnt[p];
int dir=(ch[p][]==now);
if (anc)
{
ch[anc][ch[anc][]==p]=now;
}
pnt[now]=anc;
ch[p][-dir]=ch[now][dir];
pnt[ch[now][dir]]=p;
pnt[p]=now;
ch[now][dir]=p;
up(p);
up(now);
}
void Reverse(int now)
{
rev[ch[now][]]^=;
rev[ch[now][]]^=;
swap(ch[now][],ch[now][]);
swap(lx[ch[now][]],rx[ch[now][]]);
swap(lx[ch[now][]],rx[ch[now][]]);
up(now);//容易忽略,由於改變了子節點的lx,rx值,需要更新
}
void Reset(int now,int v)//注意
{
lx[now]=rx[now]=v*siz[now];
mx[now]=sum[now]=siz[now]*v;
val[now]=v;
chgf[now]=v;
}
void down(int now)
{
if (rev[now])
{
Reverse(now);//
rev[now]=;
}
if (chgf[now]!=INF)
{
Reset(ch[now][],chgf[now]);
Reset(ch[now][],chgf[now]);
chgf[now]=INF;
}
}
void up(int now)
{
if (!now)
{
//cout<<"Update error"<<endl;;
throw "Update 0";
}
sum[now]=sum[ch[now][]]+sum[ch[now][]]+val[now];
siz[now]=siz[ch[now][]]+siz[ch[now][]]+;
lx[now]=sum[ch[now][]]+val[now]+lx[ch[now][]];
lx[now]=max(lx[now],sum[ch[now][]]+val[now]);
if (ch[now][])lx[now]=max(lx[now],lx[ch[now][]]); rx[now]=sum[ch[now][]]+val[now]+rx[ch[now][]];
rx[now]=max(rx[now],sum[ch[now][]]+val[now]);
if (ch[now][])rx[now]=max(rx[now],rx[ch[now][]]); mx[now]=max(max(val[now]+rx[ch[now][]],val[now]+lx[ch[now][]])
,max(val[now],val[now]+rx[ch[now][]]+lx[ch[now][]]));
if (ch[now][])mx[now]=max(mx[now],mx[ch[now][]]);
if (ch[now][])mx[now]=max(mx[now],mx[ch[now][]]);
}
int Splay(int now,int tp=)
{
int x=now;
tops=-;
if (now==tp)return now;
while (x!=)/**/
{
stack[++tops]=x;
x=pnt[x];
}
while (tops>=)
down(stack[tops--]);
while (pnt[now]!=tp)/**/
{
int p=pnt[now],anc=pnt[p];
if (anc==tp)/**/
{
Rotate(now);
}else
{
if ((ch[anc][]==p) == (ch[p][]==now))
{
Rotate(p);
Rotate(now);
}else
{
Rotate(now);
Rotate(now);
}
}
}
if (!tp)root=now;
return now;
}
int Get_kth(int now,int rk)
{
down(now);//這裏要先下放標記
if (rk==siz[ch[now][]]+)
{
return now;
}
if (siz[ch[now][]]<rk)
return Get_kth(ch[now][],rk--siz[ch[now][]]);
else
return Get_kth(ch[now][],rk);
}
void Insert(int pos,int v)
{
int now;
now=nextNode();
val[now]=v;
chgf[now]=INF;
rev[now]=;
mx[now]=sum[now]=v;
lx[now]=rx[now]=v;//mx 易忽略
if (!pos)
{
Splay(Get_kth(root,));
pnt[root]=now;
ch[now][]=root;
root=now;//衝定義根節點
up(now);
return ;
}else
{
Splay(Get_kth(root,pos));
pnt[root]=now;
pnt[ch[root][]]=now;
ch[now][]=root;
ch[now][]=ch[root][];
ch[root][]=;
if (root)up(root);
root=now;
up(now);
}
}
void Insert(int pos,int *arr,int n)//區間加數
{
int now=,kroot;
Build_tree(arr,now,,n-);
//Scan(now);
if (!root)
{
root=now;
return ;
}
if (!pos)
{
Splay(Get_kth(root,));
pnt[now]=root;
ch[root][]=now;
up(root);
}else if (pos==siz[root])
{
Splay(Get_kth(root,siz[root]));
pnt[now]=root;
ch[root][]=now;
up(root);
}else
{
Splay(Get_kth(root,pos));
Splay(Get_kth(root,pos+),root);
ch[ch[root][]][]=now;
pnt[now]=ch[root][];
up(ch[root][]);
up(root);
}
}
void Delete(int l,int r)
{
if (l== && r==siz[root])
{
Q.push(root);
root=;
}else if (l==)
{
Splay(Get_kth(root,r+));
Q.push(ch[root][]);
ch[root][]=;
up(root);
}else if (r==siz[root])
{
Splay(Get_kth(root,l-));
Q.push(ch[root][]);
ch[root][]=;
up(root);
}else
{
Splay(Get_kth(root,l-));
Splay(Get_kth(root,r+),root);
Q.push(ch[ch[root][]][]);
ch[ch[root][]][]=;
up(ch[root][]);
up(root);
}
}
void Scan(int now)
{
if (!now)return ;
down(now);
if (sum[now]!=sum[ch[now][]]+sum[ch[now][]]+val[now])throw "Scan_up";
if (ch[now][] && pnt[ch[now][]]!=now)throw "Scan";
Scan(ch[now][]);
printf("%d ",val[now]);
if (ch[now][] && pnt[ch[now][]]!=now)throw "Scan";
Scan(ch[now][]);
}
qword Get_sum(int l,int r)
{
if (l== && r==siz[root])
{
return sum[root];
}else if (l==)
{
Splay(Get_kth(root,r+));
return sum[ch[root][]];
}else if (r==siz[root])
{
Splay(Get_kth(root,l-));
return sum[ch[root][]];
}else
{
Splay(Get_kth(root,l-));
Splay(Get_kth(root,r+),root);
return sum[ch[ch[root][]][]];
}
}
qword Max_sum(int l,int r)
{
if (l== && r==siz[root])
{
return mx[root];
}else if (l==)
{
Splay(Get_kth(root,r+));
return mx[ch[root][]];
}else if (r==siz[root])
{
Splay(Get_kth(root,l-));
return mx[ch[root][]];
}else
{
Splay(Get_kth(root,l-));
Splay(Get_kth(root,r+),root);
return mx[ch[ch[root][]][]];
}
}
void Build_tree(int *arr,int &now,int l,int r)
{
if (r<l)return ;
int mid=(l+r)>>;
now=nextNode();
val[now]=arr[mid];
chgf[now]=INF;
rev[now]=;
mx[now]=sum[now]=arr[mid];
lx[now]=rx[now]=arr[mid];
if (l<=mid-)
Build_tree(arr,ch[now][],l,mid-);
if (mid+<=r)
Build_tree(arr,ch[now][],mid+,r);
pnt[ch[now][]]=now;
pnt[ch[now][]]=now;
up(now);
}
void Make_Reverse(int l,int r)
{
if (l== && r==siz[root])
{
Reverse(root);
up(root);
}else if (l==)
{
Splay(Get_kth(root,r+));
Reverse(ch[root][]);
up(root);
}else if (r==siz[root])
{
Splay(Get_kth(root,l-));
Reverse(ch[root][]);
up(root);
}else
{
Splay(Get_kth(root,l-));
Splay(Get_kth(root,r+),root);
Reverse(ch[ch[root][]][]);
up(ch[root][]);
up(root);//對子樹的處理都要更新至根節點
}
}
void Make_same(int l,int r,int v)
{
if (l== && r==siz[root])
{
Reset(root,v);
up(root);
}else if (l==)
{
Splay(Get_kth(root,r+));
Reset(ch[root][],v);
up(root);
}else if (r==siz[root])
{
Splay(Get_kth(root,l-));
Reset(ch[root][],v);
up(root);
}else
{
Splay(Get_kth(root,l-));
Splay(Get_kth(root,r+),root);
Reset(ch[ch[root][]][],v);
up(ch[root][]);
up(root);
}
}
}splay;
int num[MAXN];
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
//freopen("sequence7.in","r",stdin);
int i,j,k;
int x,y,z;
char opt[MAXN];
try
{
scanf("%d%d",&n,&m);
for (i=;i<n;i++)
scanf("%d",num+i);
scanf("\n");
splay.Build_tree(num,splay.root,,n-);
for (i=;i<m;i++)
{
scanf("%s",opt);
// cout<<opt<<endl;
if (opt[]=='T')//GET_SUM
{
scanf("%d%d",&x,&y);
printf(LL "\n",splay.Get_sum(x,x+y-));
}else if (opt[]=='X')//MAX_SUM
{
printf(LL"\n",splay.Max_sum(,splay.siz[splay.root]));
}else if (opt[]=='S')//INSERT
{
scanf("%d%d",&x,&y);
for (j=;j<y;j++)
{
scanf("%d",&num[j]);
}
splay.Insert(x,num,y);
}else if (opt[]=='L')//DELETE
{
scanf("%d%d",&x,&y);
splay.Delete(x,x+y-);
}else if (opt[]=='K')//MAKE_SAME
{
scanf("%d%d%d",&x,&y,&z);
splay.Make_same(x,x+y-,z);
}else if (opt[]=='V')//REVERSE
{
scanf("%d%d",&x,&y);
splay.Make_Reverse(x,x+y-);
}
//splay.Scan(splay.root);
//cout<<endl;
scanf("\n");
}
}
catch (const char * err)
{
cerr<<err<<endl;
return ;
}
return ;
}

bzoj 1500: [NOI2005]维修数列 splay的更多相关文章

  1. BZOJ 1500: [NOI2005]维修数列 (splay tree)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 4229  Solved: 1283[Submit][Status ...

  2. [BZOJ 1500] [NOI2005] 维修数列

    题目链接:BZOJ - 1500 题目分析 我要先说一下,这道题我写了一晚上,然后Debug了一整个白天..........再一次被自己的蒟蒻程度震惊= = 这道题是传说中的Splay维护数列的Bos ...

  3. BZOJ 1500 [NOI2005]维修数列 FHQ Treap

    终于A了这题...这题还是很好...但是我太菜...重构了三遍qwq FHQ Treap大法好!qwq...~~ Ins:直接拿输入造一棵树,把原来的树split成[1,pos],[pos+1,n], ...

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

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

  5. 【BZOJ】1500: [NOI2005]维修数列

    [算法]splay [题解]数据结构 感谢Occult的模板>_<:HYSBZ 1500 维修数列 #include<cstdio> #include<cctype> ...

  6. 【BZOJ】1500: [NOI2005]维修数列(splay+变态题)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 模板不打熟你确定考场上调试得出来? 首先有非常多的坑点...我遇到的第一个就是,如何pushu ...

  7. [NOI2005]维修数列 Splay tree 区间反转,修改,求和,求最值

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1500 Description Input 输入文件的第1行包含两个数N和M,N表示初始时数 ...

  8. BZOJ1500 [NOI2005]维修数列(Splay tree)

    [Submit][Status][Discuss] Description 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格 Inp ...

  9. BZOJ1500: [NOI2005]维修数列[splay ***]

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

随机推荐

  1. Java中的守护线程 & 非守护线程(简介)

    Java中的守护线程 & 非守护线程 守护线程 (Daemon Thread) 非守护线程,又称用户线程(User Thread) 用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守 ...

  2. TCP参数设置

    我们这里应用的是CentOS5.3,并内核使用的是2.6.18-128.el5PAE #1 SMP .修改部分TCP ,有的是为了提高性能与负载,但是存在降低稳定性的风险.有的则是安全方面的配置,则有 ...

  3. careercup-数组和字符串1.4

    1.4 编写一个方法,将字符串中的空格全部替换为“%20“.假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的”真实“长度. C++实现代码: #include<iostream> ...

  4. MapReduce链接作业

    对于简单的分析程序,我们只需一个MapReduce就能搞定,然而对于比较复杂的分析程序,我们可能需要多个Job或者多个Map或者Reduce进行计算.下面我们来说说多个Job或者多个MapReduce ...

  5. 基于bootstrap的datetimepicker插件

    1.当时使用的资源地址:http://www.bootcss.com/p/bootstrap-datetimepicker/ 2.如何让时间只显示到日期,不显示具体时刻 控制显示精度的是datetim ...

  6. mac os 终端提示 you have new mail

    这里的信息可能是由于所做的什么操作触发了发邮件的事件, 系统发送的邮件提醒. 我遇到的原因是由于运行 cron , 由于权限所导致了发邮件的事件提醒. Last login: Tue Apr 26 0 ...

  7. java 开发基础篇1环境安装--eclipse安装教程

    如何安装java环境 http://jingyan.baidu.com/article/a24b33cd59b58e19fe002bb9.html JDK download http://www.or ...

  8. 【转自CSDN】深入 Microsoft.VisualBasic.Strings.StrConv 簡繁轉換

    深入 Microsoft.VisualBasic.Strings.StrConv 簡繁轉換 昨天又遇到一個簡繁轉換的需求, 雖然這個問題以前已經處理過了, 但是以前是用自己建立的 b52gb 和 gb ...

  9. java中事件处理探究

    事件的触发可以源于用户,也可以用代码来主动设置事件的发生.如setSelected()java.awt.event中 听众接口 事件类 适配器类 ComponentListener     Conta ...

  10. CoreAnimation5-图层时间和缓冲

    图层时间 动画的发生是需要持续一段时间的,所以计时对整个概念来说至关重要.在这一章中,我们来看看CAMediaTiming,看看Core Animation是如何跟踪时间的. CAMediaTimin ...