splay学习&&补题

资料:https://blog.csdn.net/clove_unique/article/details/50630280

poj1442

Black Box

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 14683 Accepted: 6003

Description

Our Black Box represents a primitive database. It can save an integer array and has a special i variable. At the initial moment Black Box is empty and i equals 0. This Black Box processes a sequence of commands (transactions). There are two types of transactions: 

ADD (x): put element x into Black Box; 
GET: increase i by 1 and give an i-minimum out of all integers containing in the Black Box. Keep in mind that i-minimum is a number located at i-th place after Black Box elements sorting by non- descending. 

Let us examine a possible sequence of 11 transactions: 

Example 1 

N Transaction i Black Box contents after transaction Answer 

      (elements are arranged by non-descending)   

1 ADD(3)      0 3   

2 GET         1 3                                    3 

3 ADD(1)      1 1, 3   

4 GET         2 1, 3                                 3 

5 ADD(-4)     2 -4, 1, 3   

6 ADD(2)      2 -4, 1, 2, 3   

7 ADD(8)      2 -4, 1, 2, 3, 8   

8 ADD(-1000)  2 -1000, -4, 1, 2, 3, 8   

9 GET         3 -1000, -4, 1, 2, 3, 8                1 

10 GET        4 -1000, -4, 1, 2, 3, 8                2 

11 ADD(2)     4 -1000, -4, 1, 2, 2, 3, 8   


It is required to work out an efficient algorithm which treats a given sequence of transactions. The maximum number of ADD and GET transactions: 30000 of each type. 


Let us describe the sequence of transactions by two integer arrays: 


1. A(1), A(2), ..., A(M): a sequence of elements which are being included into Black Box. A values are integers not exceeding 2 000 000 000 by their absolute value, M <= 30000. For the Example we have A=(3, 1, -4, 2, 8, -1000, 2). 

2. u(1), u(2), ..., u(N): a sequence setting a number of elements which are being included into Black Box at the moment of first, second, ... and N-transaction GET. For the Example we have u=(1, 2, 6, 6). 

The Black Box algorithm supposes that natural number sequence u(1), u(2), ..., u(N) is sorted in non-descending order, N <= M and for each p (1 <= p <= N) an inequality p <= u(p) <= M is valid. It follows from the fact that for the p-element of our u sequence we perform a GET transaction giving p-minimum number from our A(1), A(2), ..., A(u(p)) sequence. 

 

Input

Input contains (in given order): M, N, A(1), A(2), ..., A(M), u(1), u(2), ..., u(N). All numbers are divided by spaces and (or) carriage return characters.

Output

Write to the output Black Box answers sequence for a given sequence of transactions, one number each line.

Sample Input

7 4
3 1 -4 2 8 -1000 2
1 2 6 6

Sample Output

3
3
1
2

题意:给定m个数按顺序插入,n次操作每次操作为ui,表示在插入ui个数后找出已插入书中第i小的数

思路:splay板题。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define MAXN 30010
int a[MAXN];
int u[MAXN];
/*ch[x][0]为左子节点,ch[x][1]为右子节点,f[x]为父节点,size[x]为子树大小,
cnt[x]为节点值的个数,key[x]为节点权值*/
int ch[MAXN][2],f[MAXN],size[MAXN],cnt[MAXN],key[MAXN];
int sz,root;
inline void clear(int x){  //清零
     ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=size[x]=0;
}
inline int get(int x){   //判断左子树还是右子树
     return ch[f[x]][1]==x;
}
inline void update(int x){  //更新节点信息,包括子树大小和节点cnt数
     if (x){
          size[x]=cnt[x];
          if (ch[x][0]) size[x]+=size[ch[x][0]];
          if (ch[x][1]) size[x]+=size[ch[x][1]];
     }
}
inline void rotate(int x){   //回转操作
     int old=f[x],oldf=f[old],which=get(x);
     ch[old][which]=ch[x][which^1];f[ch[old][which]]=old;
     f[old]=x;ch[x][which^1]=old;
     f[x]=oldf;
     if (oldf)
          ch[oldf][ch[oldf][1]==old]=x;
     update(old);update(x);
}
inline void splay(int x){  //通过rotate将x变为树根
     for (int fa;(fa=f[x]);rotate(x))
          if (f[fa])
               rotate((get(x)==get(fa)?fa:x));
     root=x;
}
inline void insert(int v){  //插入操作
     if (root==0) {sz++;ch[sz][0]=ch[sz][1]=f[sz]=0;key[sz]=v;cnt[sz]=1;size[sz]=1;root=sz;return;}
     int now=root,fa=0;
     while (1){
          if (key[now]==v){
               cnt[now]++;update(now);update(fa);splay(now);break;
          }
          fa=now;
          now=ch[now][key[now]<v];
          if (now==0){
               sz++;
               ch[sz][0]=ch[sz][1]=0;key[sz]=v;size[sz]=1;
               cnt[sz]=1;f[sz]=fa;ch[fa][key[fa]<v]=sz;
               update(fa);
               splay(sz);
               break;
          }
     }
}
inline int findx(int x){    //查找第x小的数(计算重复)
     int now=root;
     while (1){
          if (ch[now][0]&&x<=size[ch[now][0]])
               now=ch[now][0];
          else{
               int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
               if (x<=temp)
                    return key[now];
               x-=temp;now=ch[now][1];
          }
     }
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        sz=0;root=0;
        for(int i=0;i<=n;i++)clear(i);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        u[0]=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&u[i]);
            for(int j=u[i-1]+1;j<=u[i];j++)
            {
                insert(a[j]);
            }
            printf("%d\n",findx(i));
        }
    }
}

牛客2018ACM多校训练3-C

链接:https://www.nowcoder.com/acm/contest/141/C
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述

Eddy likes to play cards game since there are always lots of randomness in the game. For most of the cards game, the very first step in the game is shuffling the cards. And, mostly the randomness in the game is from this step. However, Eddy doubts that if the shuffling is not done well, the order of the cards is predictable!

To prove that, Eddy wants to shuffle cards and tries to predict the final order of the cards. Actually, Eddy knows only one way to shuffle cards that is taking some middle consecutive cards and put them on the top of rest. When shuffling cards, Eddy just keeps repeating this procedure. After several rounds, Eddy has lost the track of the order of cards and believes that the assumption he made is wrong. As Eddy's friend, you are watching him doing such foolish thing and easily memorizes all the moves he done. Now, you are going to tell Eddy the final order of cards as a magic to surprise him.

Eddy has showed you at first that the cards are number from 1 to N from top to bottom.

For example, there are 5 cards and Eddy has done 1 shuffling. He takes out 2-nd card from top to 4-th card from top(indexed from 1) and put them on the top of rest cards. Then, the final order of cards from top will be [2,3,4,1,5].

输入描述:

The first line contains two space-separated integer N, M indicating the number of cards and the number of shuffling Eddy has done.
Each of following M lines contains two space-separated integer pi, si indicating that Eddy takes pi-th card from top to (pi+si-1)-th card from top(indexed from 1) and put them on the top of rest cards.


1 ≤ N, M ≤ 105
1 ≤ pi ≤ N
1 ≤ si ≤ N-pi+1

输出描述:

Output one line contains N space-separated integers indicating the final order of the cards from top to bottom.

 

示例1

输入

复制

5 1
2 3

输出

复制

2 3 4 1 5

示例2

输入

复制

5 2
2 3
2 3

输出

复制

3 4 1 2 5

示例3

输入

复制

5 3
2 3
1 4
2 4

输出

复制

3 4 1 5 2

题意:给定1到n这n个数字,按顺序排好,现在m次操作,每次操作选择中间一个序列与前面的序列平移交换位置,求m次操作之后的序列。

思路:利用splay的翻转的函数,将这个序列和前面的序列一起翻转,在两部分分别翻转一次。rev数列来进行lazy标记需不需要翻转。

改板子改的比较丑,将就一下。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define MAXN 100010
int ch[MAXN][2],f[MAXN],size[MAXN],key[MAXN];
bool rev[MAXN];
int sz,root;
inline void clear(int x){
     ch[x][0]=ch[x][1]=f[x]=key[x]=size[x]=0;
}
inline int get(int x){
     return ch[f[x]][1]==x;
}
inline void pushdown(int x)
{
    if(rev[x])
    {
        swap(ch[x][0],ch[x][1]);
        rev[ch[x][0]]^=1;
        rev[ch[x][1]]^=1;
        rev[x]=0;
    }
}
inline void update(int x){
    if (x){
        size[x]=1;
        if (ch[x][0])
            size[x]+=size[ch[x][0]];
        if (ch[x][1]) 
        {
            size[x]+=size[ch[x][1]];
        }
     }
}    
inline void rotate(int x){
     int old=f[x],oldf=f[old],which=get(x);
     ch[old][which]=ch[x][which^1];f[ch[old][which]]=old;
     f[old]=x;ch[x][which^1]=old;
     f[x]=oldf;
     if (oldf)
          ch[oldf][ch[oldf][1]==old]=x;
     update(old);update(x);
}
inline void splay(int x){
     for (int fa;(fa=f[x]);rotate(x))
          if (f[fa])
               rotate((get(x)==get(fa)?fa:x));
     root=x;
}
inline void splay2(int x){
     for (int fa;(fa=f[x])&&f[fa];rotate(x))
          if (f[fa]&&f[fa]!=root)
               rotate((get(x)==get(fa)?fa:x));
} 

inline void build(int l,int r,int fa)
{
    if(l>r)return;
    if(l==r)
    {
        size[l]=1;
        ch[l][0]=ch[l][1]=0;
        f[l]=fa;
        if(l<fa)ch[fa][0]=l;
        else ch[fa][1]=l;
    }
    int mid = (l+r)>>1;
    build(l,mid-1,mid);
    build(mid+1,r,mid);
    f[mid] = fa;
    update(mid);
    if(mid < fa)ch[fa][0]=mid;
    else ch[fa][1]=mid;
}
inline int findx(int x){
     int now=root;
     while (1){
         pushdown(now);
          if (ch[now][0]&&x<=size[ch[now][0]])
               now=ch[now][0];
          else{
               int temp=(ch[now][0]?size[ch[now][0]]:0)+1;
               if (x<=temp)
                    return now;
               x-=temp;now=ch[now][1];
          }
     }
}
inline void reversal(int l,int r)
{
    int x = findx(l-1);
    int y=findx(r+1);
    splay(x);
    splay2(y); 
    rev[ch[y][0]]^=1;   
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(rev,0,sizeof(rev));
        n+=2;
        sz=0;root=0;
        for(int i=0;i<=n;i++)clear(i);
        for(int i=1;i<=n;i++)
            key[i]=i;
        build(1,n,0);
        sz=n;
        root=(1+n)>>1;
        int l,r;
        while(m--)
        {
            scanf("%d%d",&l,&r);
            reversal(2,l+r);   
            reversal(2,1+r);
            reversal(2+r,l+r);
        }
        for(int i=2;i<=n-1;i++)
            printf("%d%c",key[findx(i)]-1,i==n-1?'\n':' ');
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值