P1533 可怜的狗狗

漂亮小姐姐点击就送:https://www.luogu.org/problemnew/show/P1533

 

题目背景

小卡由于公务需要出差,将新家中的狗狗们托付给朋友嘉嘉,但是嘉嘉是一个很懒的人,他才没那么多时间帮小卡喂狗狗。

题目描述

小卡家有N只狗,由于品种、年龄不同,每一只狗都有一个不同的漂亮值。漂亮值与漂亮的程度成反比(漂亮值越低越漂亮),吃饭时,狗狗们会按顺序站成一排等着主人给食物。

可是嘉嘉真的很懒,他才不肯喂这么多狗呢,这多浪费时间啊,于是他每次就只给第i只到第j只狗中第k漂亮的狗狗喂食(好狠心的人啊)。而且为了保证某一只狗狗不会被喂太多次,他喂的每个区间(i,j)不互相包含。

输入输出格式

输入格式:

第一行输入两个数n,m,你可以假设n<300001 并且 m<50001;m表示他喂了m次。

第二行n个整数,表示第i只狗的漂亮值为ai。

接下来m行,每行3个整数i,j,k表示这次喂食喂第i到第j只狗中第k漂亮的狗的漂亮值。

输出格式:

M行,每行一个整数,表示每一次喂的那只狗漂亮值为多少。

输入输出样例

输入样例#1: 复制
7 2
1 5 2 6 3 7 4
1 5 3
2 7 1
输出样例#1: 复制
3
2


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=3e5+5;
const int INF=599518803;

int n,m;
int a[N];
struct Query
{
    int l,r,k,tim,ans;
}query[N];
struct Node
{
    Node *son[2];
    int key;
    int key_cnt;
    int size;
    int heap_key;
}node[N],A;

typedef Node* Tree;
Tree Root,now_node,null;

bool cmp1(const Query &a,const Query &b)
{
    return a.l<b.l;
}

bool cmp2(const Query &a,const Query &b)
{
    return a.tim<b.tim;
}

void init()
{
    srand(INF);
    node->son[0]=node->son[1]=node;
    Root=now_node=null=node;
}

inline Tree new_node(int key)
{
    ++now_node;
    now_node->key=key;
    now_node->key_cnt=1;
    now_node->heap_key=rand();
    now_node->size=1;
    now_node->son[0]=now_node->son[1]=null;
    return now_node;
}

inline void rotate(Tree &root,bool flag)
{
    Tree tmp=root->son[!flag];
    root->son[!flag]=tmp->son[flag];
    tmp->son[flag]=root;
    root->size=root->son[0]->size+root->son[1]->size+root->key_cnt;
    tmp->size=tmp->son[0]->size+tmp->son[1]->size+tmp->key_cnt;
    root=tmp;
}

void insert(Tree &root,int key)
{
    if(root==null)
        root=new_node(key);
    else if(key==root->key)
        ++root->size,++root->key_cnt;
    else
    {
        bool flag=key>root->key;
        insert(root->son[flag],key);
        ++root->size;
        if(root->heap_key<root->son[flag]->heap_key)
            rotate(root,!flag);
    }
}

void erase(Tree &root,int key)
{
    if(root==null)
        return;
    if(root->key!=key)
    {
        bool flag=key>root->key;
        erase(root->son[flag],key);
        --root->size;
    }
    else
    {
        if(root->key_cnt>1)
            --root->key_cnt,--root->size;
        if(root->son[0]==null)
            root=root->son[1];
        else if(root->son[1]==null)
            root=root->son[0];
        else
        {
            bool flag=root->son[0]->heap_key>root->son[1]->heap_key;
            rotate(root,flag);
            erase(root->son[flag],key);
            --root->size;
        }
    }
}

inline int kth(Tree root,int rank)
{
    while(root!=null)
    {
        if(rank<=root->son[0]->size)
            root=root->son[0];
        else if(rank>root->son[0]->size+root->key_cnt)
            rank-=root->son[0]->size+root->key_cnt,root=root->son[1];
        else
            return root->key;
    }
}

int main()
{
    //freopen("testdata.in","r",stdin);
    //freopen("233.out","w",stdout);
    init();
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        scanf("%d",a+i);
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k);
//        query[i].l=read(),
//        query[i].r=read(),
//        query[i].k=read(),
        query[i].tim=i;
    }
    sort(query+1,query+m+1,cmp1);
    for(int i=1;i<=m;++i)
    {
        if(i==1)
            for(int j=query[i].l;j<=query[i].r;++j)
                insert(Root,a[j]);
        else
        {
            if(query[i-1].r<query[i].l)
            {
                for(int j=query[i-1].l;j<=query[i-1].r;++j)
                    erase(Root,a[j]);
            }
            else
            {
                for(int j=query[i-1].l;j<query[i].l;++j)
                    erase(Root,a[j]);
            }
            for(int j=query[i-1].r+1;j<=query[i].r;++j)
                insert(Root,a[j]);
        }
        query[i].ans=kth(Root,query[i].k);
    }
    sort(query+1,query+m+1,cmp2);
    for(int i=1;i<=m;++i)
        printf("%d
",query[i].ans);
    return 0;
}
旋转 Treap
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;

const int N=300005;
const int M=5e4+5;

int n,m;
int a[N];
struct ASK
{
    int l,r,k;
    int tim,ans;
}ask[M];
struct NODE
{
    NODE *fa;
    NODE *son[2];
    int key,key_cnt;
    int size;
}node[N];

typedef NODE* Tree;
Tree Root,now_node,null;

inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num*f;
}

bool cmp1(const ASK &a,const ASK &b)
{
    return a.l<b.l;
}

bool cmp2(const ASK &a,const ASK &b)
{
    return a.tim<b.tim;
}

inline void init()
{
    node->fa=node->son[0]=node->son[1]=node;
    Root=now_node=null=node;
}

inline Tree new_node(int key,Tree fa)
{
    ++now_node;
    now_node->key=key;
    now_node->fa=fa;
    now_node->son[0]=now_node->son[1]=null;
    return now_node;
}

inline bool getgx(Tree root)
{
    return root->fa->son[1]==root;
}

inline void connect(Tree root,Tree fa,bool flag)
{
    if(fa==null)
        Root=root;
    else
        fa->son[flag]=root;
    if(root!=null)
        root->fa=fa;
}

inline void update(Tree root)
{
    root->size=root->son[0]->size+root->son[1]->size+root->key_cnt;
}

inline void rotate(Tree root)
{
    Tree fa=root->fa;
    Tree gfa=fa->fa;
    bool a=getgx(root),b=!a;
    connect(root->son[b],fa,a);
    connect(root,gfa,getgx(fa));
    connect(fa,root,b);
    update(fa);
    update(root);
}

inline void splay(Tree root,Tree goal)
{
    while(root->fa!=goal)
    {
        Tree fa=root->fa;
        if(fa->fa==goal)
            rotate(root);
        else
        {
            if(getgx(root)==getgx(fa))
                rotate(fa),rotate(root);
            else
                rotate(root),rotate(root);
        }
    }
}

inline void insert(int key)
{
    if(Root==null)
        Root=new_node(key,null);
    for(Tree root=Root;root!=null;root=root->son[key>root->key])
    {
        if(key==root->key)
        {
            ++root->key_cnt;
            ++root->size;
            splay(root,null);
            return;
        }
        else
            if(root->son[key>root->key]==null)
                root->son[key>root->key]=new_node(key,root);
        ++root->size;
    }
}

inline void erase(int key)
{
    if(Root==null)
        return;
    Tree root=Root;
    for(;root!=null&&root->key!=key;root=root->son[key>root->key]);
    if(root==null)
        return;
    splay(root,null);
    if(root->son[0]==null)
    {
        Root=root->son[1];
        if(Root!=null)
            Root->fa=null;
    }
    else
        if(root->son[1]==null)
        {
            Root=root->son[0];
            if(Root!=null)
                Root->fa=null;
        }
    else
    {
        Tree tmp=root->son[0];
        for(;tmp->son[1]!=null;tmp=tmp->son[1]);
        splay(tmp,root);
        Root=tmp;
        Root->fa=null;
        Root->son[1]=root->son[1];
        if(Root->son[1]!=null)
            Root->son[1]->fa=Root;
        update(Root);
    }
}

inline int query(int rank)
{
    for(Tree root=Root;root!=null;)
    {
        if(rank<=root->son[0]->size)
            root=root->son[0];
        else
            if(rank>root->son[0]->size+root->key_cnt)
                rank-=root->son[0]->size+root->key_cnt,root=root->son[1];
        else
            return root->key;
    }
}

int main()
{
//    freopen("testdata.in","r",stdin);
    init();
    n=read(),m=read();
    for(int i=1;i<=n;++i)
        a[i]=read();
    for(int i=1;i<=m;++i)
    {
        ask[i].l=read(),ask[i].r=read(),ask[i].k=read();
        ask[i].tim=i;
    }
    sort(ask+1,ask+m+1,cmp1);
    int l=ask[1].l,r=l;

    for(int i=1;i<=m;++i)
    {
        for(;l<ask[i].l;++l)
            erase(a[l]);
        for(;r<=ask[i].r;++r)
            insert(a[r]);
        ask[i].ans=query(ask[i].k);
    }
    sort(ask+1,ask+m+1,cmp2);
    for(int i=1;i<=m;++i)
        printf("%d
",ask[i].ans);
    return 0;
}
Splay
原文地址:https://www.cnblogs.com/lovewhy/p/8670653.html