BZOJ 1552 浅谈SPLAY维护区间最值
2017-08-27 20:34
288 查看
世界真的很大
虽然这道题算是splay的比较偏模板题了,但是自己想的话还是有难度
关键是怎么把SPLAY维护东西的思路转换过来,是关键
写起来虽然的却有点多但是却是意外的好调
看题先:
description:
input
输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。
output
输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,(1 < = Pi < = N),Pi表示第i次操作前第i小的物品所在的位置。 注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。
区间翻转比较好说,关键是怎么在维护序列时同时维护最小值
考虑普通平衡树在维护值域时维护最小值,就是平衡树的最左边
但是这道题维护的并不是值域,而是序列
考虑平衡树维护值域时,不仅可以知道最小值,还可以知道所有的值域信息,而这道题里面只需要知道最小值,维护值域不免有些浪费
考虑在维护序列时平衡树的每一个节点及其子树对应的是序列上连续的一段区间,这不免和线段树有些相似
而线段树维护最小值就只需要维护最小值就行了,所以我们平衡树也需要这么干
但不同的是线段树的结构是不变的,而平衡树的结构是不断改变的,并且为了对应到区间里面去,我们需要维护的,不再是最小值而已,而是包含最小值的节点的指针
注意update的时候多加一个维护最小值指针的东西
SPLAY的时候需要pushdown,原来一直不知道。。。
完整代码:
#include<stdio.h> #include<stack> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; struct number { int val,id; }aa[200010]; struct node { int sum,flag,siz; node *ch[2],*fa,*mst; void pushdown(node *nd) { if(flag) { swap(ch[0],ch[1]); if(ch[0]!=nd) ch[0]->flag^=1; if(ch[1]!=nd) ch[1]->flag^=1; flag=0; } } void update() { if(ch[0]->mst->sum < ch[1]->mst->sum) mst=ch[0]->mst; else mst=ch[1]->mst; if(sum<mst->sum) mst=this ; siz=ch[0]->siz+ch[1]->siz+1; } }pool[1000010],*tail=pool,*root,*null; stack <node*> stk; int n,m,a[200010],ans[200010]; bool cmp(const number &a,const number &b) { if(a.val==b.val) return a.id<b.id; else return a.val<b.val; } void init() { null=++tail; null->siz=0; null->ch[0]=null->ch[1]=null->mst=null; null->flag=0; null->sum=INF; } node* newnode(node *fa) { node *nd=++tail; nd->fa=fa; nd->siz=1; nd->ch[1]=nd->ch[0]=nd->mst=null; nd->flag=0; return nd; } void rot ( node*& x, int d ) { node* y=x->fa; y->ch[!d]=x->ch[d]; if(x->ch[d]!= null) x->ch[d]->fa=y ; x->fa=y->fa ; if(y->fa!=null) (y==y->fa->ch[0]) ? y->fa->ch[0]=x : y->fa->ch[1]=x; x->ch[d]=y; y->fa =x; x->update(); y->update(); } node *build(node *fa,int lf,int rg) { if(lf>rg) return null; node *nd=newnode(fa); if(lf==rg) { nd->sum=a[lf]; nd->mst=nd; return nd; } int mid=(lf+rg)>>1; nd->sum=a[mid]; nd->mst=nd; nd->ch[0]=build(nd,lf,mid-1); nd->ch[1]=build(nd,mid+1,rg); nd->update(); return nd; } void Splay(node *nd,node *tar) { for(node *i=nd;i!=tar;i=i->fa) stk.push(i); while(!stk.empty()) stk.top()->pushdown(null) ,stk.pop(); while(nd->fa!=tar) { node *ne=nd->fa; if(nd==ne->ch[0]) { if(ne->fa!=tar&&ne==ne->fa->ch[0]) rot(ne,1); rot(nd,1); } else { if(ne->fa!=tar&&ne==ne->fa->ch[1]) rot(ne,0); rot(nd,0); } } if(tar==null) root=nd; } node *kth(node *nd,int K) { nd->pushdown(null); if(nd->ch[0]->siz+1==K) return nd; if(nd->ch[0]->siz+1>K) return kth(nd->ch[0],K); else return kth(nd->ch[1],K-nd->ch[0]->siz-1); } void rev(int L,int R) { node *x=kth(root,L);node *y=kth(root,R+2); Splay(x,null); Splay(y,root); y->ch[0]->flag^=1; } node *qumin(int pos) { node *x=kth(root,pos),*y=kth(root,n+2); Splay(x,null); Splay(y,root); return y->ch[0]->mst; } int main() { init(); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&aa[i].val),aa[i].id=i; sort(aa+1,aa+n+1,cmp); for(int i=1;i<=n;i++) a[aa[i].id]=i; a[0]=a[n+1]=INF; root=build(null,0,n+1); for(int i=1;i<=n;i++) { node *x=qumin(i); Splay(x,null); ans[i]=x->ch[0]->siz; rev(i,ans[i]); } for(int i=1;i<n;i++) printf("%d ",ans[i]); printf("%d",ans ); return 0; } /* EL PSY CONGROO */
嗯,就是这样
相关文章推荐
- [SPLAY维护区间][BZOJ 3223][TYVJ 1729]文艺平衡树
- bzoj 1552: [Cerc2007]robotic sort && bzoj 3506: [Cqoi2014]排序机械臂(splay区间翻转)
- BZOJ3506 BZOJ1552 排序机械臂 Splay区间翻转(数组版自底向上的写法)
- bzoj 1014: [JSOI2008]火星人prefix(splay维护区间+Hash+二分)
- bzoj3729: Gty的游戏 阶梯博弈 Splay维护dfs序
- bzoj 2300: [HAOI2011]防线修建(splay动态维护凸包)
- 【bzoj3506/1552】【robotic sort】【splay】
- BZOJ 1251 Splay维护序列
- 【BZOJ3956】Count,单调栈+ST表维护区间最大值
- Bzoj3786星系探索:splay维护dfs序
- BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)
- BZOJ 1014 JSOI 2008 火星人prefix Splay维护字符串Hash + 二分
- 【BZOJ】1798: [Ahoi2009]Seq 维护序列seq 线段树多标记(区间加+区间乘)
- BZOJ 3207 浅谈主席树及哈希表对于区间数列存在性判断问题的应用
- 【bzoj 1552】【bzoj 3506】排序机械臂robotic sort(Splay)
- HDU1754 Splay 区间维护
- 【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解
- [bzoj1500][NOI2005 维修数列] (splay区间操作)
- Splay 区间信息的维护与查询 静态模板
- bzoj 1552(splay)