【bzoj1500】 noi2005—维护数列
http://www.lydsy.com/JudgeOnline/problem.php?id=1500 (题目链接)
题意
要求维护数列,操作有区间删除,区间插入,区间反转,区间修改,区间求和,求最大连续子段。
Solution
愿有生之年再也不写splay。代码模的hzwer。
2017.3.24:upd了一下代码。
代码
- // baoj1500
- #include<algorithm>
- #include<iostream>
- #include<cstdlib>
- #include<cstring>
- #include<cstdio>
- #include<cmath>
- #include<queue>
- #define LL long long
- #define inf (1ll<<30)
- #define Pi acos(-1.0)
- #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
- using namespace std;
- inline int gi() {
- int x=0,f=1;char ch=getchar();
- while (ch<'0' || ch>'9') {if (ch=='-') f=-1;ch=getchar();}
- while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
- return x*f;
- }
- const int maxn=1000010;
- int a[maxn],fa[maxn],n,m,rt,sz;
- char ch[30];
- struct node {
- int lx,rx,mx,val,sum,size,son[2],rev,tag;
- int& operator [] (int x) {return son[x];}
- }tr[maxn];
- queue<int> q;
- void pushup(int k) {
- int l=tr[k][0],r=tr[k][1];
- tr[k].size=tr[l].size+tr[r].size+1; //子树大小
- tr[k].sum=tr[l].sum+tr[r].sum+tr[k].val; //区间和
- tr[k].mx=max(tr[l].mx,tr[r].mx); //最大连续段
- tr[k].mx=max(tr[k].mx,tr[l].rx+tr[k].val+tr[r].lx);
- tr[k].lx=max(tr[l].lx,tr[l].sum+tr[k].val+tr[r].lx); //左端最大区间
- tr[k].rx=max(tr[r].rx,tr[r].sum+tr[k].val+tr[l].rx); //右端最大区间
- }
- void pushdown(int k) {
- int l=tr[k][0],r=tr[k][1];
- if (tr[k].tag) {
- tr[k].tag=tr[k].rev=0; //赋成同一个值,反不反转都一样
- if (l) tr[l].tag=1,tr[l].val=tr[k].val,tr[l].sum=tr[l].val*tr[l].size;
- if (r) tr[r].tag=1,tr[r].val=tr[k].val,tr[r].sum=tr[r].val*tr[r].size;
- if (tr[k].val>=0) {
- if (l) tr[l].lx=tr[l].rx=tr[l].mx=tr[l].sum;
- if (r) tr[r].lx=tr[r].rx=tr[r].mx=tr[r].sum;
- }
- else {
- if (l) tr[l].lx=tr[l].rx=0,tr[l].mx=tr[l].val;
- if (r) tr[r].lx=tr[r].rx=0,tr[r].mx=tr[r].val;
- }
- }
- if (tr[k].rev) {
- tr[k].rev^=1,tr[l].rev^=1,tr[r].rev^=1;
- swap(tr[l].lx,tr[l].rx),swap(tr[l][0],tr[l][1]);
- swap(tr[r].lx,tr[r].rx),swap(tr[r][0],tr[r][1]);
- }
- }
- void rotate(int x,int &k) {
- int y=fa[x],z=fa[y],l,r;
- l=tr[y][1]==x;r=l^1;
- if (y==k) k=x;
- else tr[z][tr[z][1]==y]=x;
- fa[tr[x][r]]=y;fa[y]=x;fa[x]=z;
- tr[y][l]=tr[x][r];tr[x][r]=y;
- pushup(y),pushup(x); //注意更新顺序
- }
- void splay(int x,int &k) {
- while (x!=k) {
- int y=fa[x],z=fa[y];
- if (y!=k) {
- if ((tr[y][0]==x) ^ (tr[z][0]==y)) rotate(x,k);
- else rotate(y,k);
- }
- rotate(x,k);
- }
- }
- int find(int k,int x) {
- pushdown(k);
- if (tr[tr[k][0]].size+1==x) return k;
- else if (x<=tr[tr[k][0]].size) return find(tr[k][0],x);
- else return find(tr[k][1],x-tr[tr[k][0]].size-1);
- }
- void recycle(int k) { //清空
- if (tr[k][0]) recycle(tr[k][0]);
- if (tr[k][1]) recycle(tr[k][1]);
- q.push(k);tr[k][0]=tr[k][1]=tr[k].tag=tr[k].rev=0; //节点回收入队,重复利用
- }
- int split(int l,int r) { //抠出区间
- int x=find(rt,l),y=find(rt,r+2);
- splay(x,rt),splay(y,tr[x][1]);
- return tr[y][0];
- }
- int query(int l,int r) {
- return tr[split(l,r)].sum;
- }
- void modify(int l,int r,int val) {
- int x=split(l,r),y=fa[x];
- tr[x].val=val;tr[x].tag=1;tr[x].sum=tr[x].size*val;
- if (val>=0) tr[x].lx=tr[x].rx=tr[x].mx=tr[x].sum;
- else tr[x].lx=tr[x].rx=0,tr[x].mx=val;
- pushup(y),pushup(fa[y]);
- }
- void reverse(int l,int r) {
- int x=split(l,r),y=fa[x];
- if (!tr[x].tag) {
- tr[x].rev^=1;
- swap(tr[x][0],tr[x][1]);
- swap(tr[x].lx,tr[x].rx);
- pushup(y),pushup(fa[y]);
- }
- }
- void erase(int l,int r) {
- int x=split(l,r),y=fa[x];
- recycle(x);tr[y][0]=0;
- pushup(y),pushup(fa[y]);
- }
- void build(int &k,int l,int r,int f) {
- int mid=(l+r)>>1;
- if (!q.empty()) k=q.front(),q.pop();else k=++sz;
- tr[k].sum=tr[k].val=a[mid];fa[k]=f;
- tr[k].lx=tr[k].rx=tr[k].mx=max(0,a[mid]);
- if (l<mid) build(tr[k][0],l,mid-1,k);
- if (r>mid) build(tr[k][1],mid+1,r,k);
- pushup(k);
- }
- void insert(int k,int tot) {
- for (int i=1;i<=tot;i++) scanf("%d",&a[i]);
- int x,y,z;
- build(z,1,tot,0);
- x=find(rt,k+1),y=find(rt,k+2); //因为有"哨兵",实际上是find k,k+1
- splay(x,rt),splay(y,tr[x][1]); //因为k,k+1,所以tr[y][0]为空
- fa[z]=y;tr[y][0]=z;pushup(y),pushup(x); //注意pushup的顺序
- }
- int main() {
- n=gi(),m=gi();
- tr[0].mx=a[1]=a[n+2]=-inf;
- for (int i=1;i<=n;i++) a[i+1]=gi();
- build(rt,1,n+2,0);
- while (m--) {
- int k,tot,val;scanf("%s",ch);
- if (ch[0]!='M' || ch[2]!='X') k=gi(),tot=gi();
- if (ch[0]=='I') insert(k,tot);
- else if (ch[0]=='D') erase(k,k+tot-1);
- else if (ch[0]=='M') {
- if (ch[2]=='X') printf("%d\n",tr[rt].mx);
- else scanf("%d",&val),modify(k,k+tot-1,val);
- }
- else if (ch[0]=='R') reverse(k,k+tot-1);
- else if (ch[0]=='G') printf("%d\n",query(k,k+tot-1));
- }
- return 0;
- }
【bzoj1500】 noi2005—维护数列的更多相关文章
- [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MB Description Input 输入的第1 行包含两个数N 和M(M ≤20 ...
- [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec Mem ...
- 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列
339. [NOI2005] 维护数列 时间限制:3 s 内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际 ...
- [BZOJ1500][NOI2005]维修数列---解题报告
Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...
- [NOI2005] 维护数列
[NOI2005] 维护数列 题目 传送门 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格) 操作编号 输入文件中的格式 说明 1 ...
- [BZOJ1500][NOI2005]维修数列 解题报告 Splay
Portal Gun:[BZOJ1500][NOI2005]维修数列 有一段时间没写博客了,最近在刚数据结构......各种板子背得简直要起飞,题目也是一大堆做不完,这里就挑一道平衡树的题来写写好了 ...
- P2042 [NOI2005]维护数列 && Splay区间操作(四)
到这里 \(A\) 了这题, \(Splay\) 就能算入好门了吧. 今天是个特殊的日子, \(NOI\) 出成绩, 大佬 \(Cu\) 不敢相信这一切这么快, 一下子机房就只剩我和 \(zrs\) ...
- 洛谷 P2042 [NOI2005]维护数列-Splay(插入 删除 修改 翻转 求和 最大的子序列)
因为要讲座,随便写一下,等讲完有时间好好写一篇splay的博客. 先直接上题目然后贴代码,具体讲解都写代码里了. 参考的博客等的链接都贴代码里了,有空再好好写. P2042 [NOI2005]维护数列 ...
- P2042 [NOI2005]维护数列[splay或非旋treap·毒瘤题]
P2042 [NOI2005]维护数列 数列区间和,最大子列和(必须不为空),支持翻转.修改值.插入删除. 练码力的题,很毒瘤.个人因为太菜了,对splay极其生疏,犯了大量错误,在此记录,望以后一定 ...
- Luogu P2042 [NOI2005]维护数列(平衡树)
P2042 [NOI2005]维护数列 题意 题目描述 请写一个程序,要求维护一个数列,支持以下\(6\)种操作:(请注意,格式栏中的下划线'_'表示实际输入文件中的空格) 输入输出格式 输入格式: ...
随机推荐
- PAT 1022. D进制的A+B (20)
输入两个非负10进制整数A和B(<=230-1),输出A+B的D (1 < D <= 10)进制数. 输入格式: 输入在一行中依次给出3个整数A.B和D. 输出格式: 输出A+B的D ...
- JS 关闭 页面 浏览器 事件
JS监听关闭浏览器事件关键字: js监听关闭浏览器事件Onunload与OnbeforeunloadOnunload,onbeforeunload都是在刷新或关闭时调用,可以在<script&g ...
- Html5 Egret游戏开发 成语大挑战(五)界面切换和数据处理
经过前面的制作,使用Egret的Wing很快完成了开始界面和选关卡界面,下面通常来说就是游戏界面,但此时界面切换和关卡数据还没有准备好,这次讲解界面的切换和关卡数据的解析.前面多次修改了Main.ts ...
- android values目录的读取优先级
android项目新建时会有一个values目录(高版本会增加values-v11,values-v14目录),该目录用于存放显示相的配置数据的定义文件,如strings.xml, style.xml ...
- Handler 消息传递机制
1,Handler 的概念Handler 是用来干什么的?1)执行计划任务,可以在预定的时间执行某些任务,可以模拟定时器 2)线程间通信.在Android的应用启动时,会创建一个主线程,主线程会创建一 ...
- Kth Smallest Element in a BST
Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. Not ...
- 学习C++.Primer.Plus 6 分支语句和逻辑操作符
||. &&操作符是一个顺序点 < 操作符从左向右结合 ; < age < )//17<age为true, = 1,肯定 < 27.所以为整个条件为tru ...
- 基于VirtualBox安装Ubuntu图文教程
基于VirtualBox虚拟机安装Ubuntu图文教程 一. 下载安装VirtualBox 官网下载VirtualBox,目前版本:VirtualBox 5.1.8 for Windows hosts ...
- C/C++实践笔记_002编译和链接
1.要卡死程序用异步,同步的话开一个就关一个值为非0死循环.预处理优先于编译,别称预编译main函数死循环2.程序总是从main函数开始执行的C语言本身不提供输入输出语句print等来自于stdio库 ...
- [BZOJ1264][AHOI2006]Match(DP+树状数组)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1264 分析: 考虑做一般的LCS的时候,更新结果的条件是a[i]==b[j]时候 于是 ...