伸展树+二分hdu3436(多校联合)

来源:互联网 发布:非理性繁荣 知乎 编辑:程序博客网 时间:2024/06/06 07:07

Online JudgeOnline ExerciseOnline TeachingOnline ContestsExercise AuthorF.A.Q
Hand In Hand
Online Acmers
Forum | Discuss
Statistical Charts

Problem Archive
Realtime Judge Status
Authors Ranklist
 
     C/C++/Java Exams     
ACM Steps
Go to Job
Contest LiveCast
ICPC@China
Best Coder beta
VIP | STD Contests
Virtual Contests 
    DIY | Web-DIY beta
Recent Contests
Author lee
Mail Mail 0(0)
Control Panel Control Panel 
Sign Out Sign Out
New~ 关于举办杭电程序设计竞赛(2014'12)的报名通知 
【比赛提醒】BestCoder 你报名了吗?(点击报名) 
【科普】什么是BestCoder?如何参加?

Queue-jumpers

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2423    Accepted Submission(s): 626


Problem Description
Ponyo and Garfield are waiting outside the box-office for their favorite movie. Because queuing is so boring, that they want to play a game to kill the time. The game is called “Queue-jumpers”. Suppose that there are N people numbered from 1 to N stand in a line initially. Each time you should simulate one of the following operations:
1.  Top x :Take person x to the front of the queue
2.  Query x: calculate the current position of person x
3.  Rank x: calculate the current person at position x
Where x is in [1, N].
Ponyo is so clever that she plays the game very well while Garfield has no idea. Garfield is now turning to you for help.
 

Input
In the first line there is an integer T, indicates the number of test cases.(T<=50)
In each case, the first line contains two integers N(1<=N<=10^8), Q(1<=Q<=10^5). Then there are Q lines, each line contain an operation as said above. 
 

Output
For each test case, output “Case d:“ at first line where d is the case number counted from one, then for each “Query x” operation ,output the current position of person x at a line, for each “Rank x” operation, output the current person at position x at a line.
 

Sample Input
39 5Top 1Rank 3Top 7Rank 6Rank 86 2Top 4Top 57 4Top 5Top 2Query 1Rank 6
 

Sample Output
Case 1:358Case 2:Case 3:36

每次找第k个,返回的是他的编号,所以直接把在原数组中的编号,作为伸展树中的编号就可以实现移动后能根据在原数组中的标号在树种找到他

首先离散化一下,把top中没出现的整段作为一个点,出现的作为一个点,然后就是正常的伸展树操作了

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;#define Key_value ch[ch[root][1]][0]const int maxn=200010;int s[maxn],e[maxn];int N,Q,cnt;int ch[maxn][2],pre[maxn],size[maxn],key[maxn],num[maxn];int root,tot1,tot2;struct Qu{    char str[10];    int x;}q[maxn];int p[maxn];void NewNode(int &r,int f,int val){    r=val;    ch[r][0]=ch[r][1]=0;    pre[r]=f;    key[r]=val;    size[r]=num[r]=e[val]-s[val]+1;}void pushup(int r){    size[r]=size[ch[r][0]]+size[ch[r][1]]+num[r];}void build(int &x,int l,int r,int f){    if(l>r)return;    int mid=(l+r)>>1;    NewNode(x,f,mid);    build(ch[x][0],l,mid-1,x);    build(ch[x][1],mid+1,r,x);    pushup(x);}void init(){    root=tot1=tot2=0;    ch[root][0]=ch[root][1]=num[root]=size[root]=key[root]=0;    build(root,1,cnt,0);    pushup(root);}void Rotate(int x,int kind){    int y=pre[x];    ch[y][!kind]=ch[x][kind];    pre[ch[x][kind]]=y;    if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x;    pre[x]=pre[y];    ch[x][kind]=y;    pre[y]=x;    pushup(y);}void Splay(int r,int goal){    while(pre[r]!=goal)    {        if(pre[pre[r]]==goal)        {            Rotate(r,ch[pre[r]][0]==r);        }        else        {            int y=pre[r];            int kind=(ch[pre[y]][0]==y);            if(ch[y][kind]==r)            {                Rotate(r,!kind);                Rotate(r,kind);            }            else            {                Rotate(y,kind);                Rotate(r,kind);            }        }    }    pushup(r);    if(goal==0)root=r;}int binary(int x){    int l=1,r=cnt;    while(l<=r)    {        int mid=(l+r)>>1;        if(x>=s[mid]&&x<=e[mid])return mid;        if(x<s[mid])r=mid-1;        else l=mid+1;    }    return -1;}int get_min(int r){    while(ch[r][0])    {        r=ch[r][0];    }    return r;}void Query(int x){    int r=binary(x);    Splay(r,0);    printf("%d\n",size[ch[root][0]]+x-s[r]+1);}int get_kth(int r,int k){    int t=size[ch[r][0]];    if(k<=t)return get_kth(ch[r][0],k);    else if(k<=t+num[r])return s[r]+k-t-1;    else return get_kth(ch[r][1],k-t-num[r]);}void Rank(int x){    printf("%d\n",get_kth(root,x));}void Delete(){    if(ch[root][0]==0||ch[root][1]==0)    {        root=ch[root][0]+ch[root][1];        pre[root]=0;        return ;    }    int k=get_min(ch[root][1]);    Splay(k,root);    Key_value=ch[root][0];    root=ch[root][1];    pre[ch[root][0]]=root;    pre[root]=0;    pushup(root);}void Top(int x){    int r=binary(x);    Splay(r,0);    Delete();    Splay(get_min(root),0);    ch[r][0]=0,ch[r][1]=root;    pre[root]=r;    root=r;    pre[root]=0;    pushup(root);}int main(){    int T,cas=1;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&N,&Q);        int t=0;        for(int i=1;i<=Q;i++)        {            scanf("%s%d",q[i].str,&q[i].x);            if(q[i].str[0]=='T')                p[t++]=q[i].x;        }        cnt=0;        p[t++]=1,p[t++]=N;        sort(p,p+t);        t=unique(p,p+t)-p;        for(int i=0;i<t;i++)        {            if(i>0&&p[i]-p[i-1]>1)            {                cnt++;                s[cnt]=p[i-1]+1;                e[cnt]=p[i]-1;            }            cnt++;            s[cnt]=e[cnt]=p[i];        }        init();        printf("Case %d:\n",cas++);        for(int i=1;i<=Q;i++)        {            if(q[i].str[0]=='T')Top(q[i].x);            else if(q[i].str[0]=='Q')Query(q[i].x);            else Rank(q[i].x);        }    }    return 0;}



0 0