TYVJ P1742 - [NOI2005]维护序列
来源:互联网 发布:实体店跟淘宝的一样吗 编辑:程序博客网 时间:2024/05/21 12:46
SOL:用了这么强大的数据结构。。。看到这句话就学习了“三鲜师傅评论说splay-tree功能更强大,并且有很多其他数据结构无法实现的功能”。这功能各种强大,运用函数比较多。慢慢理解吧~看完这个突然对线段树恍然大悟啊。
# include<cstdio># include<algorithm> using std::swap;using std::max; # define LL long long # define inf 1<<29# define keytree (chd[chd[root][1]][0])# define N 500005 int fa[N],chd[N][2],val[N],sz[N]; int root,tot1,tot2;int q[N],s[N]; //回收内存 int num[N];int sam[N],sum[N],lx[N],rx[N],mx[N]; bool rev[N]; /* * Splay Tree * 所处理的数组下标为1-N,为实现方便,在0和N+1的位置增加一个key为keyInf的结点 * select()函数中的kth与实际下边的关系如下 * keyInf - num - num - num - num - keyInf * 0 1 2 3 4 5 * 另外用0节点替换空节点 * * 注意1.每次插入,修改,翻转等操作后需要旋转keytree到根节点,以维护相关值 splay(keytree,0).删除操作特外,PushUp进行更新 * 注意2.初始化节点0的相关值必须根据题意调整,如mx,lx,rx... * 注意3.PushDown操作时,只要该节点打上标记了,就必须更新该节点的相关值,懒惰标记只是起到标记作用(可查看rev操作) */ /* * 更新关键字 */void PushUp(int x){ int lson=chd[x][0],rson=chd[x][1]; sz[x]=sz[lson]+1+sz[rson]; sum[x]=sum[lson]+val[x]+sum[rson]; mx[x]=max(mx[lson],mx[rson]); mx[x]=max(mx[x],max(0,rx[lson])+val[x]+max(0,lx[rson])); lx[x]=max(lx[lson],sum[lson]+val[x]+max(0,lx[rson])); rx[x]=max(rx[rson],sum[rson]+val[x]+max(0,rx[lson]));} void update_rev(int x){ if(x) { rev[x]^=1; swap(chd[x][0],chd[x][1]); swap(lx[x],rx[x]); }} void update_sam(int x,int c){ if(x) { sam[x]=1; val[x]=c; sum[x]=sz[x]*c; mx[x]=lx[x]=rx[x]=max(c,sz[x]*c); }} /* * 标记下放 */void PushDown(int x) { if(rev[x]) { update_rev(chd[x][0]); update_rev(chd[x][1]); rev[x]=0; } if(sam[x]) { update_sam(chd[x][0],val[x]); update_sam(chd[x][1],val[x]); sam[x]=0; }} /* * 旋转操作, t=0 表示左旋, t=1 表示右旋 */void rotate(int x,int t){ int y=fa[x]; PushDown(y); PushDown(x); chd[y][!t]=chd[x][t]; fa[chd[x][t]]=y; fa[x]=fa[y]; if(fa[x]) chd[fa[y]][chd[fa[y]][1]==y]=x; chd[x][t]=y; fa[y]=x; PushUp(y);} /* * 旋转使x成为goal的子节点,若goal为0则x旋转为根节点 */void splay(int x,int goal) { PushDown(x); while(fa[x]!=goal) { if(fa[fa[x]]==goal) rotate(x,chd[fa[x]][0]==x); else { int y=fa[x],z=fa[y]; int t=(chd[z][0]==y); if(chd[y][t]==x) rotate(x,!t),rotate(x,t); else rotate(y,t),rotate(x,t); } } PushUp(x); if(goal==0) root=x;} /* * 找到位置为k的节点,返回其值,并将其升至x的儿子 */int select(int k,int goal) { int x=root; PushDown(x); while(sz[chd[x][0]]!=k) { if(k<sz[chd[x][0]]) x=chd[x][0]; else { k-=(sz[chd[x][0]]+1); x=chd[x][1]; } PushDown(x); } int kth=val[x]; splay(x,goal); return kth;} /* * 将以x为根的整棵子树删除掉,并回收内存 */void erase(int x) { int f=fa[x],head=0,tail=0; for(q[tail++]=x;head<tail;head++) { s[tot2++]=q[head]; if(chd[q[head]][0]) q[tail++]=chd[q[head]][0]; if(chd[q[head]][1]) q[tail++]=chd[q[head]][1]; } chd[f][chd[f][1]==x]=0; PushUp(f);} /* * 在x节点处生成一个新的节点,值为x,父节点为f,之前删除的节点会放到s中以便再利用 */void newnode(int &x,int v,int f) { if(tot2) x=s[--tot2]; else x=++tot1; chd[x][0]=chd[x][1]=0; sum[x]=mx[x]=val[x]=v; lx[x]=rx[x]=max(0,v); sam[x]=rev[x]=0; fa[x]=f; sz[x]=1;} /* * 用num数组中[l,r]区间内的值建树 */void build(int &x,int l,int r,int f) { if(l<=r) { int m=(l+r)>>1; newnode(x,num[m],f); build(chd[x][0],l,m-1,x); build(chd[x][1],m+1,r,x); PushUp(x); }} /* * 进行初始化工作,根据题意调整0节点的相关值,其他不需要挑战呢个 */void init(){ chd[0][0]=chd[0][1]=fa[0]=sz[0]=0; root=tot1=tot2=0; sum[0]=rev[0]=0; mx[0]=lx[0]=rx[0]=-inf; newnode(root,-1,0); newnode(chd[root][1],-1,root); sz[root]=2;} /* * 1.在pos后插入tot个数据(tot个数据存于num数组中) */ void Insert(int pos,int tot) { select(pos,0); select(pos+1,root); build(keytree,1,tot,chd[root][1]); splay(keytree,0);} /* * 2.删除从pos开始的tot个数据 */void Delete(int pos,int tot) //2.删除 { select(pos-1,0); select(pos+tot,root); erase(keytree); PushUp(chd[root][1]); PushUp(root);} /* * 3.从pos开始的tot个数据都转变成c */void MakeSame(int pos,int tot,int c) { select(pos-1,0); select(pos+tot,root); update_sam(keytree,c); splay(keytree,0);} /* * 4.从pos开始的tot个数据进行翻转 */void Reverse(int pos,int tot) { select(pos-1,0); select(pos+tot,root); update_rev(keytree); splay(keytree,0);} /* * 5.获取从pos开始的tot个数据和 */void GetSum(int pos,int tot) //5.求和{ select(pos-1,0); select(pos+tot,root); printf("%d\n",sum[keytree]);} /* * 6.最大自序列和 */void MaxSum() { select(0,0); select(sz[root]-1,root); printf("%d\n",mx[keytree]);} int main(){ int i,j,n,m,pos,tot,l,r,c; char op[20]; while(scanf("%d%d",&n,&m)!=EOF) { init(); for(i=1;i<=n;i++) scanf("%d",&num[i]); build(keytree,1,n,chd[root][1]); splay(keytree,0); for(i=1;i<=m;i++) { scanf("%s",op); if(op[2]=='S') { scanf("%d%d",&pos,&tot); for(j=1;j<=tot;j++) scanf("%d",&num[j]); Insert(pos,tot); } else if(op[2]=='L') { scanf("%d%d",&pos,&tot); Delete(pos,tot); } else if(op[2]=='K') { scanf("%d%d%d",&pos,&tot,&c); MakeSame(pos,tot,c); } else if(op[2]=='V') { scanf("%d%d",&pos,&tot); Reverse(pos,tot); } else if(op[2]=='T') { scanf("%d%d",&pos,&tot); GetSum(pos,tot); } else MaxSum(); } } return 0;}
- TYVJ P1742 - [NOI2005]维护序列
- noi2005 维护序列。 splay
- [noi2005][treap]序列维护
- 【平衡树维护序列】BZOJ1500(NOI2005)[维修数列]题解
- 【noi2005】维护数列
- [NOI2005] 维护数列 sequence
- 【NOI2005】【splay】维护数列
- 数列维护 NOI2005
- 【SPLAY】NOI2005 维护数列
- 【noi2005】维护数列
- NOI2005维护数列
- noi2005维护数列 splay
- JZOJ2413. 【NOI2005】维护数列
- 【NOI2005】维护数列
- 【NOI2005】维护数列
- [NOI2005] 维护数列
- [题解]NOI2005 维护数列
- noi2005维护数列
- Ashx Session
- 塔机市场电商网络 销售钱景无限
- Android中集成第三方软件包(.jar, .so)
- SVN服务器搭建和使用
- 当你查询性能视图的时候遇到科学计数法...
- TYVJ P1742 - [NOI2005]维护序列
- Expect Unix系统中用来进行自动化控制脚本
- ubuntu下安装Apache+PHP+Mysql
- android:listview显示table效果,并有固定不动的表头(手把手教你,详细)不重写listview类,可复制到eclipse中进行运行
- TCP的连接与终止
- 小技巧-1-取未知字符串长度中数字
- asm盘与物理盘的对应关系
- 第九次上机实验
- android porterDuff 详解