前言

写写比较麻烦的这题

题目相关

题目大意

写一个大数据结构

数据范围

20000
题目链接

前置

先过模板题,比如会个非旋treap,写一下,通过[luogu3369][模板]普通平衡树
possible version

#include<cstdio>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#define rg register
namespace fast_IO
{const int IN_LEN=1000000,OUT_LEN=1000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);}
}
using namespace fast_IO;
#define getchar() getchar_()
#define putchar(x) putchar_((x))
typedef long long ll;
template<typename T>inline T min(const T x,const T y){return x<y?x:y;}
template<typename T>inline T max(const T x,const T y){return x>y?x:y;}
template<typename T>inline T abs(const T x){return x>0?x:-x;}
template<typename T>inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);}
template<typename T>inline void swap(T&a,T&b){const T c=a;a=b;b=c;}
template<typename T>inline void read(T&x)
{char cu=getchar();bool fla=0;x=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x;
}
template<typename T>inline void printe(const T x)
{if(x>=10)printe(x/10);putchar(x%10+'0');
}
template<typename T>inline void print(const T x)
{if(x<0)putchar('-'),printe(-x);else printe(x);
}
const int maxn=500001;
struct Point
{int x,key,lson,rson,size;
}Q[maxn];int usd,root;
int newnode(const int v)
{usd++;Q[usd]=(Point){v,rand(),0,0,1};return usd;
}
void update(const int x)
{Q[x].size=Q[Q[x].lson].size+Q[Q[x].rson].size+1;
}
std::pair<int,int> split(const int x,const int v)
{std::pair<int,int>res(0,0);if(!x)return res;if(Q[x].x<=v){res=split(Q[x].rson,v);Q[x].rson=res.first;res.first=x;}else{res=split(Q[x].lson,v);Q[x].lson=res.second;res.second=x;}update(x);return res;
}
int merge(int x,int y)
{if(!x)return y;if(!y)return x;if(Q[x].key<Q[y].key){Q[x].rson=merge(Q[x].rson,y);update(x);return x;}else{Q[y].lson=merge(x,Q[y].lson);update(y);return y;}
}
void insert(const int x)
{std::pair<int,int> R=split(root,x);root=merge(merge(R.first,newnode(x)),R.second);
}
void del(const int x)
{std::pair<int,int> R=split(root,x),T=split(R.first,x-1);if(T.second==0)return;root=merge(merge(T.first,merge(Q[T.second].lson,Q[T.second].rson)),R.second);
}
int rerank(int v)
{int x=root,ans=0;while(x){if(Q[x].x<v)ans+=Q[Q[x].lson].size+1,x=Q[x].rson;else x=Q[x].lson;}return ans+1;
}
int atrank(int rk)
{int x=root;while(1){const int all=Q[Q[x].lson].size+1;if(all==rk)return Q[x].x;if(all<rk)x=Q[x].rson,rk-=all;else x=Q[x].lson;}
}
int prec(int v)
{int x=root,ans=0;while(x){if(Q[x].x<v)ans=Q[x].x,x=Q[x].rson;else x=Q[x].lson;}return ans;
}
int succ(int v)
{int x=root,ans=0;while(x){if(Q[x].x>v)ans=Q[x].x,x=Q[x].lson;else x=Q[x].rson;}return ans;
}
int n;
int main()
{read(n),srand(time(0));for(rg int i=1;i<=n;i++){int opt,x;read(opt),read(x);if(opt==1)insert(x);else if(opt==2)del(x);else if(opt==3)print(rerank(x)),putchar('\n');else if(opt==4)print(atrank(x)),putchar('\n');else if(opt==5)print(prec(x)),putchar('\n');else print(succ(x)),putchar('\n');}return flush(),0;
}

题解

我们发现这里是要维护序列,那么我们需要把split魔改一下,改成“把第1-x个数放到左子树,其余放到右子树”

接下来我们考虑操作
首先我们发现初始在treap中的那些数等价于一次insert操作,所以在此不讨论
接下来,讲述每个操作的做法

  • 插入
    这个操作按一般平衡树操作就可以了

版本1(代码已删除):
我的代码中把log变成了sort的,rand值直接从上到下填即可

版本2(本文代码):
构造笛卡尔树,复杂度变成次数log加上数量了,减小常数

  • 删除
    直接旋出来那棵树,不过值得注意的是,需要对节点进行回收,否则空间复杂度受不了
  • 修改
    打个子树修改标记即可
  • 翻转
    打个子树修改标记即可
  • 求和
    记录子树权值和即可
  • 求和最大的子列
    记录子列中最大的子段,最大前缀,最大后缀
    值得注意的是,由于题目所述的区间长度必须大于0,所以要注意负权点的处理

这题看起来非常的简单,其实在具体实现过程中要注意各个标记之间的影响,需要实现好
另外,注意翻转标记下传是翻转状态,不然很容易调不出来
code

#include<cstdio>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#define rg register
namespace fast_IO
{const int IN_LEN=1000000,OUT_LEN=1000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);}
}
using namespace fast_IO;
#define getchar() getchar_()
#define putchar(x) putchar_((x))
typedef long long ll;
template<typename T>inline T min(const T x,const T y){return x<y?x:y;}
template<typename T>inline T max(const T x,const T y){return x>y?x:y;}
template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;}
template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;}
template<typename T>inline T abs(const T x){return x>0?x:-x;}
template<typename T>inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);}
template<typename T>inline void swap(T&a,T&b){const T c=a;a=b;b=c;}
template<typename T>inline void read(T&x)
{char cu=getchar();bool fla=0;x=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x;
}
template<typename T>inline void printe(const T x)
{if(x>=10)printe(x/10);putchar(x%10+'0');
}
template<typename T>inline void print(const T x)
{if(x<0)putchar('-'),printe(-x);else printe(x);
}
const int maxn=500001;
struct Point//平衡树节点
{int x,key,lson,rson,size;int zuoda,youda,zhong,he;bool flag;int change;
}Q[maxn];int root;
void blbl(const int x)
{if(!x)return;printf("%d\n",Q[x].x);blbl(Q[x].lson);blbl(Q[x].rson);
}
int rubbish[maxn],top;
int newnode(const int R)//新建节点 传入rand
{int usd=rubbish[top--];Q[usd]=(Point){0,R,0,0,1,0,0,0,0,0,-1001};return usd;
}
void change(Point&hos,const int x)//改变单点的x
{hos.x=x;maxd(hos.zuoda,x),maxd(hos.youda,x);hos.zhong=x;hos.he+=x;
}
void deal_flag(Point&hos)//解决翻转
{swap(hos.lson,hos.rson);swap(hos.zuoda,hos.youda);hos.flag^=1;
}
void deal_change(Point&hos,const int x)//解决赋值
{hos.x=x;if(x>0)hos.zuoda=hos.youda=hos.zhong=hos.he=hos.size*x;else hos.zuoda=hos.youda=0,hos.zhong=x,hos.he=hos.size*x;hos.change=x;
}
void down(Point&hos)//下传标记
{int w=hos.lson;if(w){if(hos.flag)deal_flag(Q[w]);if(hos.change!=-1001)deal_change(Q[w],hos.change);}w=hos.rson;if(w){if(hos.flag)deal_flag(Q[w]);if(hos.change!=-1001)deal_change(Q[w],hos.change);}hos.flag=0,hos.change=-1001;
}
void update(Point&hos)//更新
{Point&L=Q[hos.lson],&R=Q[hos.rson];hos.size=L.size+R.size+1;hos.he=L.he+R.he+hos.x;hos.zuoda=max(L.zuoda,L.he+hos.x+R.zuoda);hos.youda=max(R.youda,R.he+hos.x+L.youda);hos.zhong=max(max(L.zhong,R.zhong),L.youda+hos.x+R.zuoda);
}
std::pair<int,int> split(const int x,const int kth)
{std::pair<int,int>res(0,0);if(!x)return res;down(Q[x]);if(Q[Q[x].lson].size+1==kth){res.first=x,res.second=Q[x].rson;Q[x].rson=0;}else if(Q[Q[x].lson].size+1<kth){res=split(Q[x].rson,kth-(Q[Q[x].lson].size+1));Q[x].rson=res.first;res.first=x;}else{res=split(Q[x].lson,kth);Q[x].lson=res.second;res.second=x;}update(Q[x]);return res;
}
int merge(int x,int y)
{if(!x)return y;if(!y)return x;down(Q[x]),down(Q[y]);if(Q[x].key<Q[y].key){Q[x].rson=merge(Q[x].rson,y);update(Q[x]);return x;}else{Q[y].lson=merge(x,Q[y].lson);update(Q[y]);return y;}
}
int m,P[maxn],Ptop;
char opt[11];int opttop;
int STA[maxn],Stop,ID[maxn];
int maker()
{int rando=rand();STA[Stop=1]=newnode(rando),ID[Stop]=P[1];for(rg int i=2;i<=Ptop;i++){int ME=newnode(rando);rando=rand();bool fla=0;while(Stop>1&&rando<Q[STA[Stop]].key)Q[STA[Stop-1]].rson=STA[Stop],change(Q[STA[Stop]],ID[Stop]),update(Q[STA[Stop]]),Stop--,fla=1;if(rando<Q[STA[Stop]].key){change(Q[STA[Stop]],ID[Stop]),update(Q[STA[Stop]]);Q[ME].lson=STA[Stop];STA[Stop]=ME,ID[Stop]=P[i];}else{if(fla){Q[STA[Stop]].rson=0;Q[ME].lson=STA[Stop+1];}STA[++Stop]=ME,ID[Stop]=P[i];}}while(Stop>1)Q[STA[Stop-1]].rson=STA[Stop],change(Q[STA[Stop]],ID[Stop]),update(Q[STA[Stop]]),Stop--;change(Q[STA[Stop]],ID[Stop]),update(Q[STA[Stop]]);return STA[1];
}
void insert(const int x)
{std::pair<int,int>T=split(root,x);root=merge(merge(T.first,maker()),T.second);
}
void rerubbish(const int x)
{if(!x)return;rubbish[++top]=x;rerubbish(Q[x].lson),rerubbish(Q[x].rson);
}
void del(const int x)
{std::pair<int,int>T=split(root,x),S=split(T.second,Ptop);rerubbish(S.first);root=merge(T.first,S.second);
}
int samv;
void sam(const int x)
{std::pair<int,int>T=split(root,x),S=split(T.second,Ptop);deal_change(Q[S.first],samv);root=merge(merge(T.first,S.first),S.second);
}
void reverse(const int x)
{std::pair<int,int>T=split(root,x),S=split(T.second,Ptop);deal_flag(Q[S.first]);root=merge(merge(T.first,S.first),S.second);
}
int sum(const int x)//complete
{std::pair<int,int>T=split(root,x),S=split(T.second,Ptop);int res=Q[S.first].he;root=merge(merge(T.first,S.first),S.second);return res;
}
int bigv(const int x)//compete
{return Q[root].zhong;
}
int main()
{Q[0].zhong=-(0x7f7f7f7f);for(rg int i=1;i<=500000;i++)rubbish[++top]=i;read(Ptop),read(m),srand(time(0));for(rg int i=1;i<=Ptop;i++)read(P[i]);insert(0);for(rg int i=1;i<=m;i++){int x;opt[opttop=1]=getchar();while(opt[1]<'A'||opt[1]>'Z')opt[1]=getchar();while(opt[opttop]!=' '&&opt[opttop]!='\n'&&opt[opttop]!=EOF)opt[++opttop]=getchar();if(opt[1]=='I'){read(x),read(Ptop);for(rg int i=1;i<=Ptop;i++)read(P[i]);insert(x);}else if(opt[1]=='D'){read(x),read(Ptop);x--;del(x);} else if(opt[3]=='K'){read(x),read(Ptop),read(samv);x--;sam(x);}else if(opt[1]=='R'){read(x),read(Ptop);x--;reverse(x);}else if(opt[1]=='G'){read(x),read(Ptop);x--;print(sum(x)),putchar('\n');}else print(bigv(root)),putchar('\n');}return flush(),0;
}

总结

一道较为繁琐的数据结构,调了有一会儿,马上就要csp了,还得加强代码熟练度

[luogu2042] [NOI2005]维护数列相关推荐

  1. BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay)

    BZOJ 1500 Luogu P2042 [NOI2005] 维护数列 (Splay) 手动博客搬家: 本文发表于20180825 00:34:49, 原地址https://blog.csdn.ne ...

  2. 数据结构(Splay平衡树):COGS 339. [NOI2005] 维护数列

    339. [NOI2005] 维护数列 时间限制:3 s   内存限制:256 MB [问题描述] 请写一个程序,要求维护一个数列,支持以下 6 种操作:(请注意,格式栏 中的下划线' _ '表示实际 ...

  3. [NOI2005]维护数列

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

  4. [NOI2005]维护数列 恶心到毁天灭地的splay

    传送门 debug到死2333. 虽然说是splay维护序列模板,作为蒟蒻的我还是GG %%%考场A的dalao Orz  Orz. 其实不开long long也行,inf开成0x3f3f3f3f也可 ...

  5. [BZOJ1500][NOI2005]维修数列(splay)

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 16266  Solved: 5410 [Submit][Sta ...

  6. 数据结构之fhq-treap——Chef and Sets,[HNOI2012]永无乡,Play with Chain,[NOI2005]维修数列(结构体版代码)

    因为非常板,所以主要是代码 Tyvj 1728 普通平衡树 Chef and Sets [HNOI2012]永无乡 Play with Chain [NOI2005]维修数列 题目很水,所以可能会出现 ...

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

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

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

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

  9. JZOJ 2413. 【NOI2005】维护数列

    Description 请写一个程序,要求维护一个数列,支持以下6种操作:(请注意,格式栏中的下划线' _ '表示实际输入文件中的空格) 1. 插入 INSERT_posi_tot_c1_c2_-_c ...

最新文章

  1. table row设置cell的html,display:table、display:table-row和display:table-cell的用法_html/css_WEB-ITnose...
  2. android 获取活动栈,活动的生命周期系列(1)返回栈
  3. Atom使用方法(快捷键,插件,汉化)
  4. cobalt strick 4.0系列教程(3)---数据管理
  5. windos下安装redis
  6. 手机如何访问电脑局域网文件共享服务器,数据共享 手机怎么访问电脑文件?多个设备之间数据共享...
  7. coursera 视频总是缓冲或者无法观看,有什么方法解决?
  8. [洛谷P5340][TJOI2019]大中锋的游乐场
  9. 近一半程序员单身、年薪低于 15 万,程序员扎心现状大调查!
  10. windows服务器上安装的有mysql环境怎么创建数据库_Windows环境MySQL数据库安装方法...
  11. centos7/RHEL7最小化系统安装gnome图形界面
  12. pin码计算器网页版_PIN码计算锦集
  13. ictclas包 java_ICTCLAS分词系统Java调用接口在Eclipse中的安装
  14. 2023.04.22更新大麦网移动端/M端抢购软件和使用教程
  15. Linux下查找结构体定义的位置
  16. 40Gbit/s QSFP光模块的软件实现(硕士学位论文)错误指出
  17. The props`strategy` cannot be null when uses class based sharding strategy
  18. Kaggle比赛心得
  19. 10大最具影响力人物
  20. 硬件设计——外围电路(复位电路)

热门文章

  1. 重载练习2_判断方法的正确重载
  2. 初始springCloud
  3. 静态static的内存图
  4. 单继承-继承的概念和语法
  5. linux下测试个人主页,一键建站集成软件包,Linux上快速搭建测试个人网站
  6. 200818C链表的查询插入删除
  7. mybatis中条件表达式if的test为字符串时值比较
  8. 『原创』+『参考』使用C#在PPC的Today界面上的任务栏加入应用程序图标
  9. 管理本地多个SSH Key
  10. 命令行开启windows下的iis信息服务,开启及配置http端口,开启及配置ftp端口