【HDU 4441】 Queue Sequence(Splay)
来源:互联网 发布:ansys cfd软件 编辑:程序博客网 时间:2024/04/28 14:59
这道题也是一道splay的基础操作的集合题,主要包含有三种操作:
insert p :在p位置插入当前未出现的最小的数,如当前出现了1 2 3 6,那再插入4
且正数和负数同时插入,而负数插入的位置要求:该负数左边负数的个数和该数的相反数的左边的正数的个数一样多且最为靠右
则若2左边有4个正数,那么-2就应该插入在满足左边有4个负数的最靠右的位置
而如何找到最小的数呢?用一个优先队列维护一下应该不难想到
remove p:删除p以及-p。这个操作只需要在插入的时候记录一下p和-p的地址就好了
query p:计算从p到 -p的和为多少。只需要将p旋为根,将-p旋为右子树,那么关键树就是区间的和,维护一下子树和应该OK的
下面是代码:
#include<cstdio>#include<queue>#include<cstring>#include<algorithm>#define keytree (ch[ ch[root][1] ][0])typedef long long LL;using namespace std;const int SIZEN = 200005;struct SplayTree{ int ch[SIZEN][2]; int pre[SIZEN]; int sz[SIZEN]; int top,top2,root,rest; priority_queue<int,vector<int>,greater<int> > q; inline void pushup(int x){ sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1; cnt[x] = cnt[ ch[x][0] ] + cnt[ ch[x][1] ] + (val[x] < 0); sum[x] = sum[ ch[x][0] ] + sum[ ch[x][1] ] + val[x]; } inline void Rotate(int x,int f){ int y = pre[x]; ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[y]) ch[ pre[y] ][ ch[ pre[y] ][1] == y ] = x; ch[x][f] = y; pre[y] = x; pushup(y); } inline void Splay(int x,int goal){ while(pre[x] != goal){ if(pre[ pre[x] ] == goal) Rotate(x,ch[ pre[x] ][0] == x); else{ int y = pre[x],z = pre[y]; int f = ch[z][0] == y; if(ch[y][f] == x){ Rotate(x,!f),Rotate(x,f); } else{ Rotate(y,f),Rotate(x,f); } } } pushup(x); if(goal == 0) root = x; } inline void Rotateto(int k,int goal){ int x = root; while(sz[ ch[x][0] ] != k){ if(sz[ ch[x][0] ] > k){ x = ch[x][0]; } else{ k -= sz[ ch[x][0] ] + 1; x = ch[x][1]; } } Splay(x,goal); } inline void init(){ ch[0][0] = ch[0][1] = pre[0] = 0; sz[0] = val[0] = sum[0] = 0; cnt[0] = 0; while(!q.empty()) q.pop(); top = top2 = root = rest = 0; root = Newnode(0); ch[root][1] = Newnode(0); sz[root] = 2; pre[ ch[root][1] ] = root; pre[root] = 0; } int Newnode(int c){ int x = ++top; ch[x][0] = ch[x][1] = pre[0] = 0; val[x] = sum[x] = c; sz[x] = 1; cnt[x] = (c < 0); if(c > 0) loc[c] = x; else n_loc[-c] = x; return x; } int Find(int k,int x){ if(cnt[ ch[x][0] ] + 1 == k && val[x] < 0) return x; if(cnt[ ch[x][0] ] >= k) return Find(k,ch[x][0]); else return Find(k - cnt[ ch[x][0] ] - (val[x] < 0),ch[x][1]); } inline int findmax(int x){ while(ch[x][1]) x = ch[x][1]; return x; } inline int findmin(int x){ while(ch[x][0]) x = ch[x][0]; return x; } inline void debug(){ printf("root:%d\n",root); Travel(root); } void Travel(int x){ if(ch[x][0]) Travel(ch[x][0]); printf("node:%d lson:%d rson:%d pre:%d sz:%d cnt:%d val:%d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],cnt[x],val[x]); if(ch[x][1]) Travel(ch[x][1]); } void Insert(){ int c,p; scanf(" %d",&p); if(!q.empty()) {c = q.top(),q.pop();} else c = ++top2; Rotateto(p,0); Rotateto(p + 1,root); keytree = Newnode(c); rest++; pre[keytree] = ch[root][1]; pushup(ch[root][1]); pushup(root); Splay(keytree,0); int n_cnt = sz[ ch[root][0] ] - cnt[ ch[root][0] ]; if(cnt[root] < n_cnt){ Rotateto(rest,0); Rotateto(rest + 1,root); keytree = Newnode(-c); pre[keytree] = ch[root][1]; pushup(ch[root][1]); pushup(root); } else{ int lloc = Find(n_cnt,root); Splay(lloc,0); int x = findmax(ch[root][0]); Splay(x,0); Splay(lloc,root); keytree = Newnode(-c); pre[keytree] = ch[root][1]; pushup(ch[root][1]); pushup(root); } rest++; } inline void del(int x){ Splay(x,0); if(!ch[root][0]){ root = ch[root][1]; pre[root] = 0; return; } int tmp = findmax(ch[root][0]); Splay(tmp,root); ch[ ch[root][0] ][1] = ch[root][1]; pre[ ch[root][1] ] = ch[root][0]; root = ch[root][0]; pre[root] = 0; pushup(root); } inline void Del(){ int c; scanf("%d",&c); del(loc[c]); del(n_loc[c]); q.push(c); rest -= 2; } inline void Query(){ int c; scanf("%d",&c); Splay(loc[c],0); Splay(n_loc[c],root); printf("%I64d\n",sum[keytree]); } LL sum[SIZEN]; int val[SIZEN],cnt[SIZEN]; int n_loc[SIZEN],loc[SIZEN];};SplayTree spt;void solve(int n){ char op[10]; spt.init(); for(int i = 0 ; i < n ; i ++){ scanf(" %s",op); if(op[0] == 'i') spt.Insert(); else if(op[0] == 'r') spt.Del(); else if(op[0] == 'q') spt.Query(); }}int main(){ int n,txt = 1; while(scanf("%d",&n) != EOF){ printf("Case #%d:\n",txt++); solve(n); }}
0 0
- 【HDU 4441】 Queue Sequence(Splay)
- HDU 4441 【Splay】 Queue Sequence
- 【HDU 4441】 Queue Sequence 【Splay】
- HDU 4441 Queue Sequence[Splay Tree]
- hdu 4441 Queue Sequence (splay + 线段树)
- hdu 4441 Queue Sequence (伸展树splay+树状数组)
- 【splay tree】 HDOJ 4441 Queue Sequence
- hdu 4441 Queue Sequence
- HDU 4441 Queue Sequence(12年天津现场,Splay+线段树)
- hdu 4441 Queue Sequence(线段树&splay数据结构的好题!)
- Hdu 4441 Queue Sequence(给定一个数确定它在Splay中的下标)
- hdu4441 Queue Sequence(线段树+splay)
- hdu 3436 Queue-jumpers(Splay)
- hdu 1908 Double Queue ( splay )
- HDU 3436 Queue-jumpers(Splay)
- HDU 3436 Queue-jumpers splay
- hdu 4441 Queue Sequence(伸展树)
- HDU 3436 Queue-jumpers (Splay tree)
- oracle 11g RAC ORA-19808: recovery destination parameter mismatch
- APN Push
- 当使用母版页时JavaScript客户端获取服务器控件的Id
- HDU 1405 The Last Practice(数学题,变态的格式)
- DERBY数据库环境搭建以及简单使用
- 【HDU 4441】 Queue Sequence(Splay)
- 部署自己的私有 DOCKER REGISTRY---经验证可行
- nginx反向代理配置
- 验证控件插图扩展控件ValidatorCalloutExtender(用于扩展验证控件)和TextBoxWatermarkExtender
- 运行时异常与一般异常的区别(转载)
- java使用jxl解析Excel
- 关于使用JAVA调用c 或者c++的DLL的吐槽
- 中文数字版atoi【Java实现】
- NYOJ 613 免费馅饼