BZOJ 1861 Book 책장 첫 번 째 는 완전히 자기 이해 로 두 드 리 는 Splay 트 리 네요.기억 해 두다

1861: [Zjoi 2006] 책장
Time Limit: 4 Sec  
Memory Limit: 64 MB
Submit: 325  
Solved: 193
[ Submit][ Status]
Description
작은 T 는 큰 책장 을 가지 고 있다.이 책장 의 구 조 는 약간 독특 하 다. 즉, 책장 안의 책 은 위 에서 아래로 한 줄 로 쌓 여 있다.그녀 는 책 마다 1 부터 n 까지 의 정수 로 번 호 를 매 겼 다.작은 T 는 책 을 읽 을 때 매번 책 한 권 을 꺼 내 서 다 본 후에 책장 에 넣 은 다음 에 한 권 을 꺼낸다.이 책 들 은 너무 매력 적 이어서, 그녀 는 다 본 후에 원래 책장 의 어떤 위치 에 놓 여 있 었 는 지 자주 잊어버린다.그러나 작은 T 는 기억력 이 매우 좋아 서 책 을 놓 을 때마다 적어도 그 책 을 꺼 낼 때의 위치 근처에 놓 을 수 있다. 예 를 들 어 그녀 가 가 져 갈 때 이 책 위 에 X 권 의 책 이 있 으 면 돌려 놓 을 때 이 책 위 에 X - 1, X 또는 X + 1 권 의 책 만 있 을 수 있다.    물론 책 을 읽다 가 갑자기 전화 가 울 리 거나 친구 가 찾 아 오 는 등 특별한 경우 도 있다.이때 부주의 한 T 군 은 책장 에 있 는 모든 책의 맨 위 나 맨 아래 에 책 을 놓 고 몸 을 돌려 떠난다.    오 랜 시간 이 지나 면 작은 T 의 책장 에 있 는 책의 순서 가 점점 어 지 러 워 지고 특정한 번 호 를 찾 는 책 은 점점 어려워 진다.그래서 그녀 는 책 관리 프로그램 을 만들어 서 책 을 읽 을 때의 동작 을 처리 하고 두 가지 질문 에 대답 해 달라 고 부탁 했다. (1) X 번호 의 책 이 책장 에 있 는 위 치 는 무엇 입 니까?(2) 위 에서 아래로 i 번 책의 번 호 는 얼마 입 니까?
Input
첫 번 째 줄 에는 두 개의 수 n, m 가 있 는데 각각 책의 개수 와 명령 의 조 수 를 나타 낸다.두 번 째 행위 n 개의 정수: 두 번 째 i 개 수 는 초기 에 위 에서 아래로 i 번 째 위치 에 놓 인 책의 번 호 를 나타 낸다.세 번 째 줄 에서 m + 2 줄 까지, 각 줄 마다 명령 이 있 습 니 다.명령 은 5 가지 형식 이 있 습 니 다.  1. Top S - S 번 호 를 가 진 서재 가 맨 위 에 있다 는 뜻 이다.  2. Bottom S - S 번 호 를 가 진 서재 가 맨 아래 에 있다 는 뜻 입 니 다.  3. Insert S T - T * 8712 ° {- 1, 0, 1}, S 번 호 를 가 진 책 위 에 X 권 의 책 이 있다 면 이 명령 은 이 책 을 돌려 놓 은 후에 그 위 에 X + T 권 의 책 이 있다 는 것 을 나타 낸다.  4. Ask S - S 번 호 를 묻 는 책 위 에 현재 몇 권 의 책 이 있 습 니까?  5. Query S - 위 에서 세 어 본 S 권 책의 번 호 를 물 어보 세 요.
 
Input:
 
10 111
1 3 2 7 5 8 10 4 9 6
Query 3
Top 5
Ask 6
Bottom 3
Ask 3
Top 6
Insert 4 -1
Query 5
Query 2
Ask 2
 
 
사실 생각 은 아무것도 없 었 습 니 다. 바로 아 날로 그 Splay 트 리 였 습 니 다.
 
//
//  1861.cpp
//  ACM_BZOJ
//
//  Created by ipqhjjybj on 13-9-9.
//  Copyright (c) 2013  ipqhjjybj. All rights reserved.
//           。    。。
//
#include 
#include 
#include 
#include 
using namespace std;
#define Key_Tree child[child[root][1]][0]

int n;
struct SplayTree{
    const static int maxn=111111;
    int n,tot,root;
    int pre[maxn],size[maxn];//flex[maxn]
    int child[maxn][2];
    int a[maxn];

    void Travel(int u){
        if(!u) return;
        printf("u=%d c0=%d c1=%d s0=%d s1=%d
",u,child[u][0],child[u][1],size[child[u][0]]+size[child[u][1]]); Travel(child[u][0]); Travel(child[u][1]); } void Push_up(int &x){ size[x]=size[child[x][0]]+size[child[x][1]]+1; } void Del_root(){ int t=root; if(child[root][1]){ root=child[root][1]; // printf("root=%d
",root); Select(1,0); child[root][0]=child[t][0]; if(child[t][0]) pre[child[t][0]]=root; }else root=child[root][0]; pre[root]=0; Push_up(root); child[t][0]=child[t][1]=0;// t size[t]=1; } //c==0 c==1 inline void Rotate(int x,int c){ int y=pre[x]; //Pushdown(y),Pushdown(x); child[y][!c]=child[x][c]; if(child[x][c]) pre[child[x][c]]=y; pre[x]=pre[y]; if(pre[y]) child[pre[y]][child[pre[y]][1]==y]=x; child[x][c]=y; pre[y]=x; Push_up(y); } void Splay(int x,int f){ //Push_down(x); while(pre[x]!=f){ int y=pre[x],z=pre[y]; //Push_down(z),Push_down(y),Push_down(x); if(pre[pre[x]]==f){ Rotate(x,child[pre[x]][0]==x); }else{ if(child[z][0]==y){ if(child[y][0]==x) Rotate(y,1),Rotate(x,1); else Rotate(x,0),Rotate(x,1); }else{ if(child[y][0]==x) Rotate(x,1),Rotate(x,0); else Rotate(y,0),Rotate(x,0); } } } Push_up(x); if(!f) root=x; } int Select(int k,int f){ int x=root; while(1){ if(k==size[child[x][0]]+1) break; if(k<=size[child[x][0]]) x=child[x][0]; else{ k-=size[child[x][0]]+1; x=child[x][1]; } } Splay(x,f); return x; } //after one number's void Insert(int t,int after){ Select(after,0); int x=Select(after+1,root); Key_Tree=t;// child[x][0]=t; pre[t]=x; Push_up(t); Push_up(x); } void Top(int t){ Select(1,0); child[root][0]=t; pre[t]=root; Push_up(t); Push_up(root); } int Find_kth(int k){ int t=root; while(1){ if(size[child[t][0]]+1==k) break; else if(size[child[t][0]]>=k) t=child[t][0]; else k-=size[child[t][0]]+1,t=child[t][1]; } return t; } void Init(int _n){ n=_n; for(int i=1;i<=n;i++) scanf("%d",a+i); memset(child,0,(n+3)*2*sizeof(int)); for(int i=1;i<=n;i++){ pre[i-1]=i; child[i][0]=i-1; size[i]=i; }pre[n]=n+1,child[n+1][0]=n,a[n+1]=n+1,pre[n+1]=0,root=n+1,a[0]=0; size[0]=0,size[n+1]=n+1; child[0][0]=child[0][1]=0; Map.clear(); for(int i=1;i<=n;i++) Map[a[i]]=i; } map Map; }spt; void Init(int n){ spt.Init(n); } int Ask(int t){ spt.Splay(t,0); return spt.size[spt.child[t][0]]; } void Top(int t){ spt.Splay(t,0); spt.Del_root(); spt.Top(t); } int Query(int k){ return spt.a[spt.Find_kth(k)]; } void Bottom(int t){ spt.Splay(t,0); spt.Del_root(); spt.Insert(t,n-1); } void Insert(int t,int val){ spt.Splay(t,0); int sz=spt.size[spt.child[t][0]]; sz+=val; if(sz==0){ // , Top(t); return; }else if(sz==n-1){ Bottom(t); return; } spt.Del_root(); spt.Insert(t,sz); } void Solve(int m){ char str[10]; int val,num; while(m--){ scanf("%s",str); if(str[0]=='Q'){//query scanf("%d",&val); printf("%d
",Query(val)); }else if(str[0]=='T'){//top scanf("%d",&val); Top(spt.Map[val]); }else if(str[0]=='A'){//ask scanf("%d",&val); printf("%d
",Ask(spt.Map[val])); }else if(str[0]=='B'){//bottom scanf("%d",&val); Bottom(spt.Map[val]); }else if(str[0]=='I'){//insert scanf("%d %d",&val,&num); if(num!=0) Insert(spt.Map[val],num); } } } int main(){ int m; scanf("%d %d",&n,&m); Init(n); Solve(m); return 0; }

좋은 웹페이지 즐겨찾기