考虑维护一颗编号树
为了插入和删除的方便,我们选择将a[0]=a[n+1]=−infa[0]=a[n+1]=-infa[0]=a[n+1]=−inf
表示填充上这个数,而且不影响最大子段和的答案。

先用buildbuildbuild建出来编号树(每次与中间为根节点,递归建左右子树)

int build(int faa,int l,int r)
{//cout<<l<<" "<<r<<endl;if (l>r) return 0;int mid = l+r >> 1;int now = newnode(a[mid]);fa[now] = faa;ch[now][0] = build(now,l,mid-1);ch[now][1] = build(now,mid+1,r);update(now);return now;
}

考虑如果求最大子段和。
跟线段树类似,对于一颗splaysplaysplay要维护一个从底向上的最长后缀和和从上到下的最长前缀和
然后要注意本题不允许为空,所以每个点的ansansans的初始值是val[x]val[x]val[x]
合并和线段树类似,要注意更新的时候,到当前点,不一定要到另一个子树中,以右子树为例子,维护从底向上的后缀和,要考虑右子树的和加上当前点,或者加上当前点和左子树的后缀和。

void update(int x)
{siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];ans[x]=val[x];if (ch[x][0] && ch[x][1]){hmy[x]=max(hmy[ch[x][1]],val[x]+sum[ch[x][1]]+hmy[ch[x][0]]);hmy[x]=max(hmy[x],val[x]+sum[ch[x][1]]);ymh[x]=max(ymh[ch[x][0]],val[x]+sum[ch[x][0]]+ymh[ch[x][1]]);ymh[x]=max(ymh[x],val[x]+sum[ch[x][0]]);ans[x]=max(ans[ch[x][0]],ans[ch[x][1]]);ans[x]=max(hmy[x],ans[x]);ans[x]=max(ans[x],ymh[x]);ans[x]=max(ans[x],ymh[ch[x][1]]+val[x]+hmy[ch[x][0]]);ans[x]=max(ans[x],ymh[ch[x][1]]+val[x]);ans[x]=max(ans[x],hmy[ch[x][0]]+val[x]);}else{if (ch[x][0]){hmy[x]=max(val[x],val[x]+hmy[ch[x][0]]);ymh[x]=max(ymh[ch[x][0]],sum[ch[x][0]]+val[x]);ans[x]=max(hmy[x],ymh[x]);ans[x]=max(ans[x],ans[ch[x][0]]);}else{if (ch[x][1]){hmy[x]=max(hmy[ch[x][1]],sum[ch[x][1]]+val[x]);ymh[x]=max(val[x],val[x]+ymh[ch[x][1]]);ans[x]=max(hmy[x],ymh[x]);ans[x]=max(ans[x],ans[ch[x][1]]);}else{hmy[x]=ymh[x]=ans[x]=val[x];}}}ans[x]=max(ans[x],val[x]);
}

对于插入操作,我们只需要找到第pospospos和第pos+2pos+2pos+2分别转到根和右儿子即可。

void insert(int pos,int x)
{int qq = kth(pos+1);int hj = kth(pos+2);splay(qq,0);splay(hj,qq);int now = newnode(x);ch[hj][0]=now;fa[now]=hj;splay(now,0);
}

这里为了节省空间,可以使用内存池,就是把用过的编号放到一个vectorvectorvector里面,每次用的时候,首先去调用vectorvectorvector里面的编号。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define pb push_back
#define mk make_pair
#define ll long long
#define lson ch[x][0]
#define rson ch[x][1]using namespace std;inline int read()
{int x=0,f=1;char ch=getchar();while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;
}const int maxn = 3e5+1e2;
const int inf = -1e9;int ch[maxn][2];
int siz[maxn];
int n,m;
int fa[maxn];
int sum[maxn];
int ymh[maxn],hmy[maxn]; //
int ans[maxn];
int val[maxn];
int root;
vector<int> rb;
int tot;
int a[maxn];int newnode(int x)
{int now = 0;if (rb.empty()){++tot;now = tot;}else{now = rb.back();rb.pop_back();}//now = ++tot;val[now]=ans[now]=ymh[now]=hmy[now]=x;siz[now]=1;return now;
}void delnode(int x)
{ans[x]=ymh[x]=hmy[x]=sum[x]=siz[x]=fa[x]=ch[x][0]=ch[x][1]=0;val[x]=0;rb.pb(x);
}void update(int x)
{siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];ans[x]=val[x];if (ch[x][0] && ch[x][1]){hmy[x]=max(hmy[ch[x][1]],val[x]+sum[ch[x][1]]+hmy[ch[x][0]]);hmy[x]=max(hmy[x],val[x]+sum[ch[x][1]]);ymh[x]=max(ymh[ch[x][0]],val[x]+sum[ch[x][0]]+ymh[ch[x][1]]);ymh[x]=max(ymh[x],val[x]+sum[ch[x][0]]);ans[x]=max(ans[ch[x][0]],ans[ch[x][1]]);ans[x]=max(hmy[x],ans[x]);ans[x]=max(ans[x],ymh[x]);ans[x]=max(ans[x],ymh[ch[x][1]]+val[x]+hmy[ch[x][0]]);ans[x]=max(ans[x],ymh[ch[x][1]]+val[x]);ans[x]=max(ans[x],hmy[ch[x][0]]+val[x]);}else{if (ch[x][0]){hmy[x]=max(val[x],val[x]+hmy[ch[x][0]]);ymh[x]=max(ymh[ch[x][0]],sum[ch[x][0]]+val[x]);ans[x]=max(hmy[x],ymh[x]);ans[x]=max(ans[x],ans[ch[x][0]]);}else{if (ch[x][1]){hmy[x]=max(hmy[ch[x][1]],sum[ch[x][1]]+val[x]);ymh[x]=max(val[x],val[x]+ymh[ch[x][1]]);ans[x]=max(hmy[x],ymh[x]);ans[x]=max(ans[x],ans[ch[x][1]]);}else{hmy[x]=ymh[x]=ans[x]=val[x];}}}ans[x]=max(ans[x],val[x]);
}int son(int x)
{if (ch[fa[x]][0]==x) return 0;else return 1;
}void rotate(int x)
{int y=fa[x],z=fa[y];int b = son(x),c = son(y);ch[z][c]=x;fa[x]=z;ch[y][b]=ch[x][!b];fa[ch[x][!b]]=y;ch[x][!b]=y;fa[y]=x;update(y);update(x);
}void splay(int x,int p)
{while (fa[x]!=p){int y = fa[x],z=fa[y];int b = son(x),c = son(y);if (z==p) rotate(x);else{if (b==c){rotate(y);rotate(x);}else{rotate(x);rotate(x);}} }if (p==0) root=x;
}int kth(int x)
{int now = root;while (1){//cerr<<now<<endl;if (x<=siz[ch[now][0]]) now = ch[now][0];else{if (x<=siz[ch[now][0]]+1) return now;x-=siz[ch[now][0]]+1;now = ch[now][1];} }
}void insert(int pos,int x)
{int qq = kth(pos+1);int hj = kth(pos+2);splay(qq,0);splay(hj,qq);int now = newnode(x);ch[hj][0]=now;fa[now]=hj;splay(now,0);
}void delet(int x)
{int qq = kth(x);int hj = kth(x+2);//cout<<"*******"<<endl;splay(qq,0);splay(hj,qq);delnode(ch[hj][0]);ch[hj][0]=0;update(hj);splay(hj,0);
}int build(int faa,int l,int r)
{//cout<<l<<" "<<r<<endl;if (l>r) return 0;int mid = l+r >> 1;int now = newnode(a[mid]);fa[now] = faa;ch[now][0] = build(now,l,mid-1);ch[now][1] = build(now,mid+1,r);update(now);return now;
}int main()
{//freopen("lwk.in","r",stdin);// freopen("a.out","w",stdout);n=read();a[0]=inf;a[n+1]=inf;for (int i=1;i<=n;i++) a[i]=read();root = build(0,0,n+1);//splay(root,0);//cout<<ans[root]<<endl;int q=read();for (int i=1;i<=q;i++){//cerr<<i<<endl;char s[10];scanf("%s",s+1);if (s[1]=='I'){int x=read(),y=read();x--;insert(x,y);}if(s[1]=='D'){int x=read();delet(x);}if (s[1]=='R'){int x=read(),y=read();//splay(x,0);int uu = kth(x+1);splay(uu,0);val[uu]=y;update(uu);}if (s[1]=='Q'){int l=read(),r=read();int qq = kth(l);int hj = kth(r+2);splay(qq,0);splay(hj,qq);cout<<ans[ch[hj][0]]<<"\n";}}return 0;
}   

SP4487 GSS6 - Can you answer these queries VI (splay)相关推荐

  1. SPOJ 4487 Can you answer these queries VI

    SPOJ_4487 其实这个题目和GSS1是差不多的,只不过由于有增加和删除的操作,这样用线段树就搞不定了,因此可以维护一个splay来实现这些操作. 但是一开始我写出的程序总是TLE,而和网上一些A ...

  2. SPOJ 4487. Can you answer these queries VI splay

    题目链接:点击打开链接 题意比較明显,不赘述. 删除时能够把i-1转到根,把i+1转到根下 则i点就在 根右子树 的左子树,且仅仅有i这一个 点 #include<stdio.h> #in ...

  3. 解题报告:SP1043 GSS4 - Can you answer these queries III(GSS线段树八部曲之三)(区间最大连续子段和)

    要注意输入的数据有坑,x可能大于y- 我们可以模块化编程,使得整个代码井井有条 函数可以重名,只要参数不一样就行. 来源 yxc老师的上课板书 然后就是简单的代码了 #include<iostr ...

  4. 解题报告:SP2713 GSS4 - Can you answer these queries IV(GSS线段树八部曲之四)

    x>yx>yx>y是真的艹. 然后就是一道模板题了. #include<bits/stdc++.h>using namespace std; typedef long l ...

  5. SP1043 GSS1 - Can you answer these queries I(线段树,区间最大子段和(静态))

    题目描述 给出了序列A[1],A[2],-,A[N]. (a[i]≤15007,1≤N≤50000).查询定义如下: 查询(x,y)=max{a[i]+a[i+1]+...+a[j]:x≤i≤j≤y} ...

  6. 【线段树】GSS5 - Can you answer these queries V(luogu-SPOJ 2916)

    正题 luogu-SPOJ 2916 题目大意 给你一个序列,有若干询问,每次给出左右端点的区间,问你最大字段和 解题思路 用线段树维护区间信息,询问的区间如果有交则分类讨论求解 code #incl ...

  7. 2019.03.24【SPOJ-GSS1】Can you answer these queries I(猫树)

    传送门 解析: 对于这种问题,如果不考虑修改的话可能会有一些做法通过预处理来降低询问复杂度 而其中一种通过增加预处理复杂度来降低询问复杂度的做法我们称之为猫树(出自猫锟的博客) 对于不带修改的区间最大 ...

  8. SP1043 GSS1 - Can you answer these queries I(猫树)

    给出了序列A[1],A[2],-,A[N]. (a[i]≤15007,1≤N≤50000).查询定义如下: 查询(x,y)=max{a[i]+a[i+1]+...+a[j]:x≤i≤j≤y}. 给定M ...

  9. 另一个画风的GSS1 - Can you answer these queries I(猫树)

    前言 其实我觉得你看猫锟的解释也看不懂(主要是还有一些不良心的讲解者不讲清楚,当然这里不是针对了qwq) 猫锟链接 Solution 考虑我们的线段树是个啥玩意? 每一层都是一堆区间叠在一起. 我们在 ...

  10. splay/fhq-treap 问卷调查反馈—— [JSOI2008]火星人prefix(splay),Strange Queries(fhq-treap)

    文章目录 [JSOI2008]火星人prefix Strange Queries [JSOI2008]火星人prefix BZOJ1014 思路很好想,哈希字符串即可 只是平衡树的码量大 注意因为sp ...

最新文章

  1. SqlServer示例数据库Northwind(一)——实体关系
  2. JDK源码解析 Runable是一个典型命令模式,Runnable担当命令的角色,Thread充当的是调用者,start方法就是其执行方法
  3. 系统app无法访问外部存储设备问题
  4. socket 编程入门教程(三)TCP原理:5、TCP的三次握手(three-way handshake)
  5. MySQL死锁案例分:先delete,再insert,导致死锁
  6. java 生成器 设计模式_Java中的生成器设计模式
  7. codeup 1128: 出租车费 贪心|找规律
  8. linux qt显示gif图片,QT显示GIF图片
  9. [转]从java角度理解cpu上下切换
  10. Android实用笔记——使用ViewFlipper实现屏幕切换动画
  11. 王不留,混迹基层八年穷屌丝,考研准备四个月,考上中国科技大学MBA,成为一家软件上市公司中层管理者(附备考攻略)
  12. fireworks8序列号:
  13. 小区门禁卡可以复制到手机上吗_手机NFC可以复制小区用的门禁卡吗?步骤是什么?...
  14. 深度学习与传统机器学习的区别
  15. 层次分析法步骤及源代码
  16. kill -HUP重启mysql_kill的用法和例句,包括kill常用短语解释和词组意思翻译,同义词,反义词【澳典网ODict.Net】...
  17. 数据采集:Flume和Logstash的工作原理和应用场景
  18. 模拟登录qq网页版方法
  19. iphone照片恢复至android,将照片从Android传输到iPhone的8种方法很容易
  20. 【微信小程序调用百度API实现图像识别功能】----项目实战

热门文章

  1. 软考项目管理十大管理及过程
  2. 2022杭州华为OD面试经历
  3. Excel Rate 函数的java 实现,等额本息计算反推利率
  4. 魔方心得-20180227
  5. 如何保证分布式系统数据一致性
  6. 用计算机计算2的31次方,2的31次方,用什么方法可以最快算出来呢
  7. 行为画像分析 行业客户画像 行业用户画像
  8. excel小技巧之--自定义序列
  9. 如何在word中的图片上画圈标注_教你如何轻松在图片上画圈圈、画箭头、写注释...
  10. 晚上几点睡才叫“熬夜”?给你“答案”,很多人都想错了