码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ_1588&Codevs_1296_[HNOI2002]_营业额统计(Treap/Splay)

时间:2016-05-13 18:56:47      阅读:245      评论:0      收藏:0      [点我收藏+]

标签:

描述


http://www.lydsy.com/JudgeOnline/problem.php?id=1588

给出每一天的营业值,求出之前的天当中与它相差最小的营业值与它的差的绝对值(第一天的差值为他本身),求和.

 

分析


比宠物收养所更裸,果然十几年前的题都是水吗...然而我只会做水题.

注意:

1.第一次写Splay的时候重复的元素直接跳过导致一直T,后来就先把这个值伸展上来再跳过,就过了,果然这种均摊的复杂度不是可以瞎玩的...

另外,不判重似乎慢不了多少...

 

 

技术分享
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int oo=~0u>>1;

struct Treap{
    struct node{
        node* ch[2];
        int v,r;
        node(int v,node* t):v(v){ ch[0]=ch[1]=t; r=rand(); }
    }* root,* null;
    Treap(){
        null=new node(0,NULL); null->r=oo;
        root=null;
    }
    void rot(node* &o,bool d){
        node* k=o->ch[!d]; o->ch[!d]=k->ch[d]; k->ch[d]=o;
        o=k;
    }
    void insert(node* &o,int x){
        if(o==null) o=new node(x,null);
        else{
            if(x==o->v) return;
            bool d=x>o->v;
            insert(o->ch[d],x);
            if(o->ch[d]->r<o->r) rot(o,!d);
        }
    }
    int pre(node* o,int x){
        if(o==null) return -oo;
        if(o->v<=x) return max(pre(o->ch[1],x),o->v);
        return pre(o->ch[0],x);
    }
    int suc(node* o,int x){
        if(o==null) return oo;
        if(o->v>=x) return min(suc(o->ch[0],x),o->v);
        return suc(o->ch[1],x);
    }
}tree;

int n,a,ans;

int main(){
    scanf("%d",&n);
    scanf("%d",&a);
    ans+=a; tree.insert(tree.root,a); n--;
    while(n--){
        if(scanf("%d",&a)==EOF) a=0;
        int pre=tree.pre(tree.root,a);
        int suc=tree.suc(tree.root,a);
        if(pre==-oo) ans+=suc-a;
        else if(suc==oo) ans+=a-pre;
        else ans+=min(suc-a,a-pre);
        tree.insert(tree.root,a);
    }
    printf("%d\n",ans);
    return 0;
}
Treap

 

技术分享
#include <cstdio>
#include <algorithm>
using namespace std;

const int oo=~0u>>1;

struct Splay{
    struct node{
        node* ch[2],*pa;
        int v;
        node(int v,node* t):v(v){ ch[0]=ch[1]=pa=t; }
        bool d(){ return pa->ch[1]==this; }
        void setc(node* t,bool d) { ch[d]=t; t->pa=this; }
    }*root,*null;
    Splay(){
        null=new node(0,NULL);
        root=null;
    }
    void rot(node* o){
        node* pa=o->pa; bool d=o->d();
        pa->pa->setc(o,pa->d());
        pa->setc(o->ch[!d],d);
        o->setc(pa,!d);
        if(pa==root) root=o;
    }
    void splay(node* o,node* pa){
        while(o->pa!=pa){
            if(o->pa->pa==pa) rot(o);
            else o->d()==o->pa->d()?(rot(o->pa),rot(o)):(rot(o),rot(o));
        }
    }
    void insert(int x){
        if(root==null){ root=new node(x,null); return; }
        node* t=root;
        if(t->v==x) return;
        while(t->ch[x>t->v]!=null&&t->ch[x>t->v]->v!=x) t=t->ch[x>t->v];
        if(t->ch[x>t->v]!=null){ splay(t->ch[x>t->v],null); return; }
        node* k=new node(x,null);
        t->setc(k,x>t->v);
        splay(k,null);
    }
    int pre(int x){
        node* t=root;
        int ret=-oo;
        while(t!=null){
            if(t->v==x) return x;
            if(t->v<x) ret=t->v,t=t->ch[1];
            else t=t->ch[0];
        }
        return ret;
    }
    int suc(int x){
        node* t=root;
        int ret=-oo;
        while(t!=null){
            if(t->v==x) return x;
            if(t->v>x) ret=t->v,t=t->ch[0];
            else t=t->ch[1];
        }
        return ret;
    }
}tree;

int n,a,ans;

int main(){
    scanf("%d",&n);
    scanf("%d",&a);
    ans+=a; tree.insert(a); n--;
    while(n--){
        if(scanf("%d",&a)==EOF) a=0;
        int pre=tree.pre(a);
        int suc=tree.suc(a);
        if(pre==-oo) ans+=suc-a;
        else if(suc==-oo) ans+=a-pre;
        else ans+=min(suc-a,a-pre);
        tree.insert(a);
    }
    printf("%d\n",ans);
    return 0;
}
Splay

 

BZOJ_1588&Codevs_1296_[HNOI2002]_营业额统计(Treap/Splay)

标签:

原文地址:http://www.cnblogs.com/Sunnie69/p/5490350.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!