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. careercup-链表 2.7

    2.7 编写一个函数,检查链表是否为回文. 思路:1)可以利用链表中的元素采用头插法创建一个新的链表,然后比较两个链表的元素是否相等.   2)利用快慢指针,将链表后半部分逆转之后,比较前半部分与后半 ...

  2. 5 Ways to Use Log Data to Analyze System Performance--reference

    Recently we looked across some of the most common behaviors that our community of 25,000 users looke ...

  3. request对象多种方法封装表单数据

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, ...

  4. Java基础知识强化之IO流笔记25:FileInputStream / FileOutputStream 复制图片案例

    1.  需求:把D:\\美女.jpg 复制到当前项目目录下mn.jpg 代码示例: package com.himi.filecopy; import java.io.FileInputStream; ...

  5. RedHat7配置IdM server

    IdM服务器是一个集成身份验证服务器. Figure 1.1. The IdM Server: Unifying Services Authentication: Kerberos KDC Kerbe ...

  6. 一个玩具程序——测试密码强度(pure C)

    替人写的C语言作业… 介绍: 程序名称:密码强度检测程序 注释风格:doxygen 测试环境:linux3.6, gcc4.7window7, vs2012 已知问题:1. 算法与参考链接不一致,结果 ...

  7. .net+easyui系列--datagrid

    加载CSS <link href="../../Public/easyui/SiteEasy.css" rel="stylesheet" type=&qu ...

  8. JS 判断 Radio 单选按钮是否为选中状态 并弹出 值信息

    今天项目中所解决的问题:JS 判断 Radio 单选按钮是否为选中状态 并弹出 值信息,一开始总是获取不到 radio 的值,后来发现逻辑存在些问题,特此共享该代码留笔记 和 分享给遇到 这类问题的 ...

  9. A题笔记(4)

    No. 1384 这题没啥 不过网考成绩出了,发现我的口语分数相较其他人还挺高的~~~哈哈哈 Code::Blocks 有时在程序运行结束后,.exe 并没有结束,因而之后无论怎么调试和修改代码,运行 ...

  10. Java SE Java EE Java ME 的区别

    Java SE(Java Platform,Standard Edition) Java SE 以前称为 J2SE.它允许开发和部署在桌面.服务器.嵌入式环境和实时环境中使用的 Java 应用程序.J ...