您的位置:首页 > 产品设计 > UI/UE

【HDU 3436】Queue-jumpers(Splay)

2014-09-13 20:41 330 查看
Splay的基础操作。问题的关键就在于N非常大,就算是利用Splay数组也是远远开不下的,因此很自然地想到了hash一下

可以将所有要进行Top的节点和Query的节点
然后对于每一个节点或者每一个段,可以将它的长度表示出来(方便起见每个点可以看做一个长度为1的线段)

剩下的就是Splay的基础操作了

1、top:将节点删除后插入到队首

2、Rank:找到当前子树的第k个数

3、Query:询问第k个人的位置。可以将该点旋转至树根,那么左子树的个数+1就是其位置

下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int SIZEN = 200025;
int txt = 1;
int has[SIZEN],cntx;
int n_val[SIZEN];
int p[SIZEN>>1];
char op[SIZEN>>1];
int read(){
char ch = ' ';
while(ch < '0' || ch > '9') ch = getchar();
int ans = 0;
while(ch <= '9' && ch >='0'){
ans *= 10;
ans += ch - '0';
ch = getchar();
}
return ans;
}
struct SplayTree{
int ch[SIZEN][2];
int pre[SIZEN];
int sz[SIZEN];
int top,root;
inline void pushup(int x){
sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + cnt[x];
}
int Newnode(int x){
pre[x] = ch[x][0] = ch[x][1] = 0;
cnt[x] = sz[x] = n_val[x + 1] - n_val[x];
return x;
}
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],n_val[x]);
if(ch[x][1]) Travel(ch[x][1]);
}
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 build(int &x,int l,int r,int f){
if(l > r) return;
int mid = (l + r) >> 1;
x = Newnode(mid);
build(ch[x][0],l,mid - 1,x);
build(ch[x][1],mid + 1,r,x);
pre[x] = f;
pushup(x);
}
inline void init(){
ch[0][0] = ch[0][1] = pre[0] = 0;
sz[0] = cnt[0] = 0;
root = top = 0;
}
int findmax(int x){
while(ch[x][1]){
x = ch[x][1];
}
return x;
}
int findmin(int x){
while(ch[x][0]){
x = ch[x][0];
}
return x;
}
inline void del(int x){
Splay(x,0);
if(ch[x][0] == 0){
root = ch[x][1];
ch[x][0] = ch[x][1] = pre[x] = 0;
pre[root] = 0;
return;
}
int m = findmax(ch[root][0]);
Splay(m,root);
ch[m][1] = ch[x][1];
ch[x][0] = ch[x][1] = 0;
pre[x] = 0;
pre[ ch[m][1] ] = m;
root = m;
pre[root] = 0;
pushup(root);
}
inline void query(int i){
int loc = p[i];
loc = upper_bound(n_val,n_val + cntx,loc) - n_val - 1;
Splay(loc,0);
printf("%d\n",sz[ ch[root][0] ] + 1);
}
inline void Top(int i){
int loc = p[i];
loc = upper_bound(n_val,n_val + cntx,loc) - n_val - 1;
del(loc);
if(root == 0){
root = loc;
ch[root][0] = ch[root][1] = 0;
pre[root] = 0;
return;
}
int Min = findmin(root);
Splay(Min,0);
ch[root][0] = loc;
pre[loc] = root;
ch[loc][0] = ch[loc][1] = 0;
pushup(loc);
pushup(root);
Splay(loc,0);
}
inline int getrank(int x,int k){
int t = sz[ ch[x][0] ];
if(t >= k)
return getrank(ch[x][0],k);
else if(k <= t + cnt[x])
return n_val[x] + k - t - 1;
else
return getrank(ch[x][1],k - t - cnt[x]);
}
inline void rank(int i){
int k = p[i],loc;
printf("%d\n",getrank(root,k));
}
int cnt[SIZEN];
};
SplayTree spt;
void Has(int &cnt,int n){
has[cnt++] = n + 1;has[cnt++] = 1;
has[cnt++] = 0;
sort(has,has+cnt);
int ncnt = 0;
n_val[ncnt++] = has[0];
for(int i=1;i<cnt;i++){
if(has[i] != has[i - 1]){
if(has[i - 1] + 1 != has[i])
n_val[ncnt++] = has[i - 1] + 1;
n_val[ncnt++] = has[i];
}
}
cnt = ncnt;
}

void solve(){
int n,q;
char t_op[10];
scanf("%d%d",&n,&q);
printf("Case %d:\n",txt++);
spt.init();
cntx = 0;
has[cntx++] = 0;
for(int i=0;i<q;i++){
scanf("%s",t_op);
p[i] = read();
op[i] = t_op[0];
if(op[i] != 'R') has[cntx++] = p[i];
}
Has(cntx,n);
spt.build(spt.root,1,cntx - 2,0);
spt.pushup(spt.root);
for(int i=0;i<q;i++){
if(op[i] == 'T') spt.Top(i);
else if(op[i] == 'R') spt.rank(i);
else if(op[i] == 'Q') spt.query(i);
}
}
int main()
{
//freopen("data.in","r",stdin);
int _;
scanf("%d",&_);
while(_--) solve();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: