暑假学习日记2013/8/5

    前几天去海南旅行没怎么做题,倒是搞了一下多校的那个polya,现在看来如果给我多点时间我应该是能搞出来的,置换群也大概知道怎么找了,以前是没看出那个东西怎么转,现在看出来了,自然就没什么好怕的了~今天在研究Treap,觉得它的名字就是Tree和Heap派生出来的,既有树的形式,也有堆的形式,通过旋转能够平衡,下面贴下代码,代码的模板来源于某道题的标程,自己在后面加了个找第k大值的,下面是模板

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
using namespace std;

int N=100000;

const int M = 100000 << 2;
int root;
int size[M], number[M], args[M], key[M], indices[M][2];
int node_count;

void update(int u) {
    size[u] = size[indices[u][0]] + size[indices[u][1]] + number[u];
}

void rotate(int &u, int d) {
    int v = indices[u][d];
    indices[u][d] = indices[v][d ^ 1];
    indices[v][d ^ 1] = u;
    update(u);
    update(v);
    u = v;
}

void insert(int &u, int k) {
    if (u == 0) {
        u = ++ node_count;
        size[u] = number[u] = 1;
        key[u] = k;
        args[u] = rand();
        indices[u][0] = indices[u][1] = 0;
    } else if (k == key[u]) {
        number[u] ++;
    } else {
        int d = k > key[u];
        int &v = indices[u][d];
        insert(v, k);
        if (args[v] < args[u]) {
            rotate(u, d);
        }
    }
    update(u);
}

void erase(int &u, int k) {
    if (u == 0) {
        size[u] = number[u] = indices[u][0] = indices[u][1] = 0;
    } else if (k == key[u]) {
        if (number[u] > 1) {
            number[u] --;
        } else {
            int d = args[indices[u][1]] < args[indices[u][0]];
            rotate(u, d);
            erase(u, k);
        }
    } else {
        int d = k > key[u];
        int &v = indices[u][d];
        erase(v, k);
        if (args[v] < args[u]) {
            rotate(u, d);
        }
    }
    update(u);
}

bool find(int u, int k) {
    while (u > 0) {
        if (key[u] == k) {
            return true;
        }
        u = indices[u][k > key[u]];
    }
    return false;
}

int find_greater(int u, int k) {
    int result = 0;
    while (u > 0) {
        if (k <= key[u]) {
            result += size[indices[u][1]] + number[u];
        }
        u = indices[u][k > key[u]];
    }
    return result;
}

int find_smaller(int u,int k){
    int result=0;
    while(u>0){
        if(k>=key[u]){
            result+=size[indices[u][0]]+number[u];
        }
        u=indices[u][k >= key[u]];
    }
    return result;
}

int find_equal(int u,int k){
    while (u > 0) {
        if (key[u] == k) {
            return number[u];
        }
        u = indices[u][k > key[u]];
    }
    return 0;
}

int find_kth(int u,int k){
    if(u==0||k<=0||k>size[u]) return 0;
    int s1=size[indices[u][0]];
    int s2=number[u];
    if(s1<k&&s1+s2>=k){
        return key[u];
    }
    else if(s1+s2<k){
        return find_kth(indices[u][1],k-s1-s2);
    }
    else if(s1>=k){
        return find_kth(indices[u][0],k);
    }
}

#define clr(x) memset((x), 0, sizeof(x))

void init(){
    clr(size);clr(number);clr(args);clr(key);clr(indices);
    args[0]=INT_MAX;
    node_count=0;
    root=0;
}


int main()
{
    init();
    int n;cin>>n;
    int otype,okey;
    while(n--)
    {
        scanf("%d%d",&otype,&okey); // 1是插入key值 2是删除key值 3是查找key值 4是询问大于等于key 5询问小于等于 6询问等于 7询问第k大的
        if(otype==1){
            insert(root,okey);
        }
        else if(otype==2){
            erase(root,okey);
        }
        else if(otype==3){
            cout<<find(root,okey)<<endl;
        }
        else if(otype==4){
            cout<<find_greater(root,okey)<<endl;
        }
        else if(otype==5){
            cout<<find_smaller(root,okey)<<endl;
        }
        else if(otype==6){
            cout<<find_equal(root,okey)<<endl;
        }
        else if(otype==7){
            cout<<find_kth(root,okey)<<endl;
        }
    }
    return 0;
}

写了个驱动程序测试了下,感觉还行,漏洞还有待发现吧.
总结一下:

1.Treap

2.Polya定理

原文地址:https://www.cnblogs.com/chanme/p/3239657.html