BZOJ4399: 魔法少女LJJ treap

题意:有⑨种操作
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 400001
using 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值