1. 程式人生 > >POJ 1442 平衡樹Treap新模板

POJ 1442 平衡樹Treap新模板

題意:輸入m個數,詢問n個數,第一個數如果是3,就輸出在m的第三個數輸入完成後第1大的數,第二個就輸出第二大的數,但前提都是在輸入完U[i]個數後

思路:用平衡樹Treap進行插入和查詢第K大的數,模版題

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=100010;
class Treap{
    public:
struct Treap_Node{
    Treap_Node *left,*right;
    int value,fix,weight,size;//fix為修正值,是隨機產生的,保證二叉樹不會退化的重要環節,wweight為權值,size為子樹大小
}*root,*null;
Treap(){
    null=new struct Treap_Node;
    null->size=0;
    null->weight=0;
    null->value=inf;
    null->left=null;
    null->right=null;
    null->fix=inf;
    root=null;
}
void Treap_Print(Treap_Node *P){//從小到大輸出
    if(P!=null){
        Treap_Print(P->left);
        printf("%d\n",P->value);
        Treap_Print(P->right);
    }
}
void Treap_Left_Rotate(Treap_Node *&a){//左旋之後仍不改變二叉樹性質
    Treap_Node *b=a->right;
    a->right=b->left;
    b->left=a;
    b->size=a->size;
    a->size=a->left->size+a->right->size+a->weight;
    a=b;
}
void Treap_Right_Rotate(Treap_Node *&a){//右旋之後仍不改變二叉樹性質
    Treap_Node *b=a->left;
    a->left=b->right;
    b->right=a;
    b->size=a->size;
    a->size=a->left->size+a->right->size+a->weight;
    a=b;
}
int Treap_Find(Treap_Node *P,int value){//查詢有沒有value這個數
    if(P==null) return 0;
    if(P->value==value) return 1;
    else if(value<P->value) return Treap_Find(P->left,value);
    else return Treap_Find(P->right,value);
}
void Treap_Insert(Treap_Node *&P,int value){//插入一個數
    if(P==null){
        P=new Treap_Node;
        P->left=P->right=null;//左右兒子均為空
        P->value=value;
        P->fix=rand();
        P->weight=1;
        P->size=1;
    }else if(value==P->value){
        P->weight++;
    }
    else if(value<P->value){
        Treap_Insert(P->left,value);
        if(P->left->fix<P->fix)
            Treap_Right_Rotate(P);
    }else{
        Treap_Insert(P->right,value);
        if(P->right->fix<P->fix)
            Treap_Left_Rotate(P);
    }
    P->size=P->left->size+P->right->size+P->weight;
}
void Treap_Delete(Treap_Node *&P,int value){//刪除一個數
    if(P==null) return ;
    if(value<P->value) Treap_Delete(P->left,value);
    else if(value>P->value) Treap_Delete(P->right,value);
    else if(P->weight>1) P->weight--;
    else if((P->left==NULL)&&(P->right==NULL)){
        delete P;
        P=NULL;
    }else{
        if(P->left->fix<P->right->fix) Treap_Left_Rotate(P);
        else Treap_Right_Rotate(P);
        Treap_Delete(P,value);
    }
    P->size=P->left->size+P->right->size+P->weight;
}
int Treap_pred(Treap_Node *P,int value,Treap_Node *optimal){//前驅
    if(P==null||value==P->value) return optimal->value;
    if(P->value<value) return Treap_pred(P->right,value,P);
    else return Treap_pred(P->left,value,optimal);
}
int Treap_succ(Treap_Node *P,int value,Treap_Node *optimal){//後繼
    if(P==null||value==P->value) return optimal->value;
    if(P->value>value) return Treap_succ(P->left,value,P);
    else return Treap_succ(P->right,value,optimal);
}
int Treap_Findkth(Treap_Node *P,int k){//求第K大的數
    if(P==null) return 0;
    int t=P->left->size;
    if(k<t+1) return Treap_Findkth(P->left,k);
    else if(k>t+P->weight) return Treap_Findkth(P->right,k-(t+P->weight));
    else return P->value;
}
int Treap_Rank(Treap_Node *P,int value,int cur){//求這個數的排名
    int t=P->left->size;
    if(value==P->value) return t+cur+1;
    else if(value<P->value) return Treap_Rank(P->left,value,cur);
    else return Treap_Rank(P->right,value,t+cur+P->weight);
}
void Treap_erase(Treap_Node *&P) {//將樹清空
		if(P->left!=null)
			Treap_erase(P->left);
		if(P->right!=null)
			Treap_erase(P->right);
		delete P;
}
};
int num[30010],num1[50010];
int main(){
    int n,a,b,m;
    while(scanf("%d%d",&n,&m)!=-1){
        Treap tree;
        for(int i=1;i<=n;i++) scanf("%d",&num[i]);
        int t=1,k=1;
        for(int i=1;i<=m;i++) scanf("%d",&num1[i]);
        while(t<=m){
            while(k<=num1[t]){
                tree.Treap_Insert(tree.root,num[k]);
                k++;
            }
            int ans=tree.Treap_Findkth(tree.root,t++);
            printf("%d\n",ans);
        }
    }
    return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=15010;
struct Node{
    Node *ch[2];
    int r,v,s;
    Node(int v):v(v){ch[0]=ch[1]=NULL;r=rand();s=1;}
    int cmp(int x){
        if(x==v) return -1;
        return x<v? 0:1;
    }
    void maintain(){
        s=1;
        if(ch[0]!=NULL) s+=ch[0]->s;
        if(ch[1]!=NULL) s+=ch[1]->s;
    }
};
void Rotate(Node* &o,int d){
    Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
    o->maintain();k->maintain();o=k;
}
void Insert(Node* &o,int x){
    if(o==NULL) o=new Node(x);
    else{
        int d=x<(o->v)? 0:1;
        Insert(o->ch[d],x);
        if(o->ch[d]->r>o->r) Rotate(o,d^1);
    }
    o->maintain();
}
void Remove(Node* &o,int x){
    int d=o->cmp(x);
    if(d==-1){
        Node* u=o;
        if(o->ch[0]!=NULL&&o->ch[1]!=NULL){
            int d2=(o->ch[0]->r>o->ch[1]->r?1:0);
            Rotate(o,d2);Remove(o->ch[d2],x);
        }else{
            if(o->ch[0]==NULL) o=o->ch[1];
            else o=o->ch[0];
            delete u;
        }
    }else Remove(o->ch[d],x);
    if(o!=NULL) o->maintain();
}
int Kth(Node* &o,int k){//第K大的值
    if(o==NULL||k<=0||k>o->s) return 0;
    int s=(o->ch[0]==NULL?0:o->ch[0]->s);
    if(k==s+1) return o->v;
    else if(k<=s) return Kth(o->ch[0],k);
    else return Kth(o->ch[1],k-s-1);
}
int Rank(Node* &o,int x){//x的排名
    if(o==NULL) return -1;//未找到
    int num=o->ch[0]==NULL?0:o->ch[0]->s;
    if(x==o->v) return num+1;
    else if(x<o->v) return Rank(o->ch[0],x);
    else return Rank(o->ch[1],x)+num+1;
}
void deletetree(Node* &o){
    if(o->ch[0]!=NULL) deletetree(o->ch[0]);
    if(o->ch[1]!=NULL) deletetree(o->ch[1]);
    delete o;o=NULL;
}
int num[30010],num1[50010];
int main(){
    int n,m,a,b;
    while(scanf("%d%d",&n,&m)!=-1){
        Node* root=NULL;
        for(int i=1;i<=n;i++) scanf("%d",&num[i]);
        for(int i=1;i<=m;i++) scanf("%d",&num1[i]);
        int t=1,k=1;
        while(t<=m){
            while(k<=num1[t]){
                Insert(root,num[k]);
                k++;
            }
            int ans=Kth(root,t++);
            printf("%d\n",ans);
        }
        deletetree(root);
    }
    return 0;
}


相關推薦

POJ 1442 平衡Treap模板

題意:輸入m個數,詢問n個數,第一個數如果是3,就輸出在m的第三個數輸入完成後第1大的數,第二個就輸出第二大的數,但前提都是在輸入完U[i]個數後 思路:用平衡樹Treap進行插入和查詢第K大的數,模版題 #include <stdio.h> #include

平衡Treap模板與原理

優化 排名 print 比較 pla ans for 後繼 每一個 這次我們來講一講Treap(splay以後再更) 平衡樹是一種排序二叉樹(或二叉搜索樹),所以排序二叉樹可以迅速地判斷兩個值的大小,當然操作肯定不止那麽多(不然我們還學什麽)。 而平衡樹在排序二叉樹的基礎上

luoguP3369[模板]普通平衡(Treap/SBT) 題解

names main getchar() clu 父親節 ble blank fine while 鏈接一下題目:luoguP3369[模板]普通平衡樹(Treap/SBT) #include<iostream> #include<cstdlib>

模板平衡——Treap和Splay

二叉搜尋樹($BST$):一棵帶權二叉樹,滿足左子樹的權值均小於根節點的權值,右子樹的權值均大於根節點的權值。且左右子樹也分別是二叉搜尋樹。(如下) $BST$的作用:維護一個有序數列,支援插入$x$,刪除$x$,查詢排名為$x$的數,查詢$x$的排名,求$x$的前驅後繼等操作。 時間複雜度:$O(運

模板】普通平衡 Treap

題目描述 您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作: 1.插入x數 2.刪除x數(若有多個相同的數,因只刪除一個) 3.查詢x數的排名(排名定義為比當前數小的數的個數+1。若有多個相同的數,因輸出最小的排名) 4.查詢

【bzoj3224】普通平衡——treap

blog lib mes cas style tree upd treap ins 我的第一道treap題目,treap的模版題。 代碼是對著hzw的敲的,一邊敲一邊理解。。。 主要是熟悉一下treap的各種基本操作,詳細細節看代碼。 #include<cstdio

3224: Tyvj 1728 普通平衡板子)

pri ati urn 多個 stdin 目標 一個 題目 page 3224: Tyvj 1728 普通平衡樹 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 17048 Solved: 7429[Submit][S

bzoj3224Tyvj 1728 普通平衡 treap

amp turn clas algo 。。 pac rip problem upd 3224: Tyvj 1728 普通平衡樹Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 17706 Solved: 7764[Submit

[洛谷P3369] 普通平衡 Treap & Splay

mes href using oid org 題目 scanf printf std 這個就是存一下板子...... 題目傳送門 Treap的實現應該是比較正經的。 插入刪除前驅後繼排名什麽的都是平衡樹的基本操作。 1 #include<cstdio>

7.Bzoj3224: Tyvj 1728 普通平衡(Treap)

Bzoj3224: Tyvj 1728 普通平衡樹(Treap) 終於自己敲出來了Treap。。。。。。拿來當板子還是挺好用的. 操作1,顯然根據二叉搜尋樹的性質直接建就好了. 操作2,如果有兩個兒子,則把這個點下旋下去,直到只有一個兒子或者沒有. 操作3,查詢比他小的數,記錄一個size,表示這個點有多少

poj 3691(AC自動機,模板)

.題意是說給了N個帶病毒的DNA串( DNA串只有AGCT幾種單元組成)...再給一長串DNA..問這長串DNA最少改動幾個(就是改..不是刪除或者新增..)能保證沒有包含病毒字串..輸出這個最小改動的次數..若怎麼修改都帶病毒子串...輸出-1... 思路:這是我第一道調

資料結構之平衡(Treap)

平衡樹是二叉搜尋樹和堆合併構成的新資料結構,所以它的名字取了Tree和Heap各一半,叫做Treap。 堆和樹的性質是衝突的,二叉搜尋樹滿足左子樹<根節點<右子樹,而堆是滿足根節點小於等於(或大於等於)左右兒子。因此在Treap的資料結構中,並不是

POJ 3107 Godfather (的重心模板題)

題意:給出一棵樹,求出所有樹的重心,並且按編號從小到大輸出。 直接套模板即可。 程式碼如下: #include<iostream> #include<cstdio> #inc

最強平衡——Treap[以我的最弱擊敗你的最強]

僕の最弱を以て,君の最強を打ち破る。!!——Treap 本人蒟蒻,在平衡樹坑中深陷數年。為了早日逃離此天坑,特作此文。 什麼是平衡樹?度娘傳送門 什麼是treap?ACdreamers%%% 注:本篇所有程式碼都在片尾!!(醒目) CMP 那麼瞭解了

BZOJ 1208 平衡Treap模版題

題意:不描述了 思路:我們只需要一個樹就可以,輸入一個數就存進去,當人和動物都大於0的時候,開始給人分配寵物,人的期望值b的排名k,找到k-1的數和k+1的數,比較哪個離b更近,人多還是動物動情況一樣不用分開討論,然後加起來取餘輸出,簡單題#include <std

洛谷P3369 普通平衡(Treap/Splay)

題目描述 您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作: 1. 插入x數 2. 刪除x數(若有多個相同的數,因只刪除一個) 3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名) 4. 查詢排名為x的數 5.

紅黑 ------ luogu P3369 【模板】普通平衡Treap/SBT)

div child lin main false tchar clas char als 二次聯通門 : luogu P3369 【模板】普通平衡樹(Treap/SBT) 近幾天閑來無事。。。就把各種平衡樹都寫了一下。。。 下面是紅黑樹(Red Black Tree)

替罪羊 ------ luogu P3369 【模板】普通平衡Treap/SBT)

nod %d clas https number problem 普通 true ble 二次聯通門 : luogu P3369 【模板】普通平衡樹(Treap/SBT) 閑的沒事,把各種平衡樹都寫寫 比較比較。。。 下面是替罪羊樹 #include &l

數組splay ------ luogu P3369 【模板】普通平衡Treap/SBT)

普通 模板 char truct div color fine col suffix 二次聯通門 : luogu P3369 【模板】普通平衡樹(Treap/SBT) #include <cstdio> #define Max 100005

fhq treap ------ luogu P3369 【模板】普通平衡Treap/SBT)

ret true read std stdin urn tdi ref code 二次聯通門 : LibreOJ #104. 普通平衡樹 #include <cstdio> #include <iostream> #include