BZOJ4399: 魔法少女LJJ treap

来源:互联网 发布:wind数据库试用 编辑:程序博客网 时间:2024/05/01 23:56

题意:有⑨种操作
1.新建一个节点,权值为x。
2.连接两个节点。
3.将一个节点a所属于的联通快内权值小于x的所有节点权值变成x。
4.将一个节点a所属于的联通快内权值大于x的所有节点权值变成x。
5.询问一个节点a所属于的联通块内的第k小的权值是多少。
6.询问一个节点a所属联通快内所有节点权值之积与另一个节点b所属联通快内所有节点权值之积的大小。
7.询问a所在联通快内节点的数量
8.若两个节点a,b直接相连,将这条边断开。
9.若节点a存在,将这个点删去。
0<=m<=400000,权值<=1000000000,c<=7

动态图问题(大嘘)
8和⑨操作并不存在。于是由于没有单点修改,比BZOJ2333还要简单。
查询第k大的时候忘了一路下推标记WA了一下午。。。
想刷点水题都刷不动,orz
代码:

#include<cstdio>#include<cmath>#include<cassert>#include<tr1/random>#define gm 400001using namespace std;struct Istream{    static const size_t str=1<<16;    char buf[str],*s,*t;    Istream():buf(),s(),t(){}    char get() {return (s==t)?(t=buf+fread(s=buf,1,str,stdin),*s++):(*s++);}    Istream& operator>> (int &x)    {        x=0;register char c;        do c=get(); while(c<'0'||c>'9');        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=get();        return *this;    }}cin;struct Ostream{    static const size_t str=1<<16;    char buf[str],*s,*t;    Ostream():buf(),s(buf),t(buf+str){}    ~Ostream(){fwrite(buf,1,s-buf,stdout);}    void put(char c){(s==t)?(fwrite(s=buf,1,str,stdout),*s++=c):(*s++=c);}    Ostream& operator<< (int x)    {        if(!x) put('0');        else        {            int a[15],t=1;            while(x) a[t++]=x%10,x/=10;            while(--t) put(a[t]+'0');        }        return *this;    }    Ostream& operator<< (const char *x)    {        while(*x) put(*x++);        return *this;    }}cout;const char *endl="\n";int m;namespace Treap{    tr1::mt19937 rnd;    struct node    {        node *l,*r;        int v,w,mark,sz;        double vx,sum;        node(int x):l(),r(),v(x),w(rnd()),mark(),sz(1),vx(log2(x)),sum(vx){}        void cast(int x,const double& __logx)        {            v=mark=x;            vx=__logx,sum=__logx*sz;        }        void down()        {            if(mark)            {                if(l) l->cast(mark,vx);                if(r) r->cast(mark,vx);                mark=0;            }        }        void up()        {            sz=1,sum=vx;            if(l) sz+=l->sz,sum+=l->sum;            if(r) sz+=r->sz,sum+=r->sum;        }    };    struct pair    {        node *fi,*se;        pair(node *fi=0,node *se=0):fi(fi),se(se){}    };    struct treap    {        private:            node *rt;            static pair split(node *a,int v)            {                if(!a) return pair();                a->down();                if(a->v<=v)                {                    pair res=split(a->r,v);                    a->r=res.fi;                    a->up();                    return pair(a,res.se);                }                else                {                    pair res=split(a->l,v);                    a->l=res.se;                    a->up();                    return pair(res.fi,a);                }            }            static node* merge(node *a,node *b)            {                if(!a) return b;                if(!b) return a;                if(a->w>b->w)                {                    a->down();                    a->r=merge(a->r,b);                    a->up();                    return a;                }                else                {                    b->down();                    b->l=merge(a,b->l);                    b->up();                    return b;                }            }            static node *join(node *a,node *b)            {                if(!a) return b;                if(!b) return a;                if(a->w>b->w)                {                    pair p=split(b,a->v);                    a->down();                    a->l=join(a->l,p.fi);                    a->r=join(a->r,p.se);                    a->up();                    return a;                }                else                {                    pair p=split(a,b->v);                    b->down();                    b->l=join(b->l,p.fi);                    b->r=join(b->r,p.se);                    b->up();                    return b;                }            }        public:            treap():rt(){}            treap(int x):rt(new node(x)){}            void join(treap &rhs)            {                rt=join(rt,rhs.rt);rhs.rt=0;            }            void lower_limit(int x)            {                pair p=split(rt,x-1);                if(p.fi) p.fi->cast(x,log2(x));                rt=merge(p.fi,p.se);            }            void upper_limit(int x)            {                pair p=split(rt,x);                if(p.se) p.se->cast(x,log2(x));                rt=merge(p.fi,p.se);            }            int find_by_order(int k)            {                node *x=rt;                while(x)                {                    x->down();                    int cnt=(x->l)?(x->l->sz):0;                    if(k==cnt+1) return x->v;                    if(k<=cnt) x=x->l;                    else k-=cnt+1,x=x->r;                }                assert(0);            }            bool operator < (const treap &rhs) const            {                return rt->sum<rhs.rt->sum;            }            int size()            {                return rt->sz;            }    };}struct union_set{    private:        int r[gm];        int tot;    public:        union_set():r(),tot(){}        int push_back()        {            return r[++tot]=tot;        }        int find(int x)        {            return r[x]==x?x:r[x]=find(r[x]);        }        void set(int x,int y)        {            r[x]=y;        }}s;typedef Treap::treap tree;tree t[gm];int main(){    cin>>m;    while(m--)    {        int a,b,c;        cin>>c>>a;        if(c!=1&&c!=7) cin>>b;        switch(c)        {            case 1:                b=s.push_back();                t[b]=tree(a);                break;            case 2:                a=s.find(a),b=s.find(b);                if(a!=b)                {                    s.set(a,b);                    t[b].join(t[a]);                }                break;            case 3:                a=s.find(a);                t[a].lower_limit(b);                break;            case 4:                a=s.find(a);                t[a].upper_limit(b);                break;            case 5:                a=s.find(a);                cout<<t[a].find_by_order(b)<<endl;                break;            case 6:                a=s.find(a),b=s.find(b);                cout<<int(t[b]<t[a])<<endl;                break;            default:                a=s.find(a);                cout<<t[a].size()<<endl;        }    }    return 0;}
0 0
原创粉丝点击