zoukankan      html  css  js  c++  java
  • UVALive 5031 Graph and Queries (Treap)

    删除边的操作不容易实现,那么就先离线然后逆序来做。

    逆序就变成了合并,用并存集判断连通,用Treap树来维护一个连通分量里的名次。

    Treap = Tree + Heap。用一个随机的优先级来平衡搜索树。

    名次查询需要维护树的结点数量,假设当前在u点,u的左子树有n个结点,那么u的就是以u为根的树上第n+1小的。

    如果查询的不是n+1,那么根据结点数量判断一下在哪颗子树上,然后去查询。

    树的合并就将结点数少的树上的点往结点数多的树里面插,然后删掉结点少的树。

    修改权值就分解成删除点和插点。

    写的时候要分清哪些指针本身是要修改的,要用引用。哪些指针可能是NULL,不应该访问。

    试过将null设定为常指针,快了25ms,用内存池模拟new 分配内存,快了50ms,但是结点数要开到maxn的两倍,(在这RE了很多次)。

    如果new 的效率足够的话还是不要用内存池了,搞不好就RE了。

    这题刷新了挂题发数,不过总算是会写Treap了。

    #include<bits/stdc++.h>
    using namespace std;
    
    struct Node
    {
        Node *ch[2];
        int v,r,s;
        void maintain()
        {
            s = 1+ch[0]->s+ch[1]->s;
        }
    };
    
    Node *const null = new Node();
    
    inline Node *newNode(int x)
    {
        Node* t = new Node();
        t->ch[0]=t->ch[1] = null;
        t->s = 1; t->r = rand(); t->v = x;
        return t;
    }
    
    void rot(Node*&o,int d)
    {
        Node*t = o->ch[d^1]; o->ch[d^1] = t->ch[d]; t->ch[d] = o;
        o->maintain(); t->maintain();
        o = t;
    }
    
    void inst(Node*&o,int x)
    {
        if(o==null){
            o = newNode(x);
        }else {
            int d = x > o->v ? 1:0;
            inst(o->ch[d],x);
            if(o->ch[d]->r > o->r) rot(o,d^1);
        }
        o->maintain();
    }
    
    inline int tcmp(int a,int b)
    {
        if(a == b) return -1;
        return a > b? 0 : 1;
    }
    
    void rmov(Node*&o,int x)
    {
        //if(o == null) return;
        int d = tcmp(o->v,x);
        if(~d){
            rmov(o->ch[d],x);
        }else {
            Node*lc = o->ch[0],*rc = o->ch[1];
            if(lc!=null &&rc != null){
                int d2 = lc->r > rc->r? 1:0;
                rot(o,d2); rmov(o->ch[d2],x);
            }else {
                Node *t = o;
                if(lc == null) o = rc;
                else o = lc;
                delete t;
            }
        }
        if(o != null) o->maintain();
    }
    
    const int maxc = 5e5+5, maxn = 2e4+5, maxm = 6e4+5;
    struct Cmd
    {
        char tp;
        int x,p;
    }cmd[maxc];
    
    int n,m,wei[maxn],fro[maxm],to[maxm],rmvd[maxm];
    
    int pa[maxn];
    int fdst(int x){ return x==pa[x]?x:pa[x]=fdst(pa[x]); }
    
    Node *rt[maxn];
    
    //k>0
    int kth(Node*o,int k)
    {
        if(o == null || k <= 0 || k > o->s) return 0; //
        int s = o->ch[1]->s;
        if(k == s+1) return o->v;
        if(k <= s) return kth(o->ch[1],k);
        return kth(o->ch[0],k-s-1);
    }
    
    void mgto(Node*&u,Node*&v)
    {
        if(u->ch[0] != null) mgto(u->ch[0],v);
        if(u->ch[1] != null) mgto(u->ch[1],v);
        inst(v,u->v);
        delete u;
        u = null;
    }
    
    void rmvTree(Node*&o)
    {
        if(o->ch[1] != null) rmvTree(o->ch[1]);
        if(o->ch[0] != null) rmvTree(o->ch[0]);
        delete o;
        o = null;
    }
    
    inline void addEdge(int i)
    {
        int u = fdst(fro[i]), v = fdst(to[i]);
        if(u != v){
            if(rt[u]->s < rt[v]->s){
                pa[u] = v;
                mgto(rt[u],rt[v]);
            }else {
                pa[v] = u;
                mgto(rt[v],rt[u]);
            }
        }
    }
    
    int qct;
    long long qtot;
    
    inline void qry(int x,int p)
    {
        if(p>0){
            qtot+=kth(rt[fdst(x)],p);
        }
        qct++;
    }
    
    inline void chgw(int x,int p)
    {
        int u = fdst(x);
        rmov(rt[u],wei[x]);
        inst(rt[u],wei[x]=p);
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int kas = 0;
        null->s = 0; null->ch[0] = null->ch[1] = null;
        fill(rt,rt+maxn,null);
        while(~scanf("%d%d",&n,&m)&&n){
            for(int i = 1; i <= n; i++) scanf("%d",wei+i);
            for(int i = 1; i <= m; i++) scanf("%d%d",fro+i,to+i);
            kas++;
    
            int c = 0;
            while(true){
                char tp; int x,p;
                scanf(" %c",&tp);
                if(tp == 'E') break;
                scanf("%d",&x);
                if(tp == 'D') rmvd[x] = kas;
                else if(tp == 'Q') scanf("%d",&p);
                else if(tp == 'C') {
                    p = wei[x];
                    scanf("%d",wei+x);
                }
                cmd[c++] = {tp,x,p};
            }
    
            for(int i = 1; i <= n; i++){
                pa[i] = i;
                if(rt[i] != null) rmvTree(rt[i]);
                rt[i] = newNode(wei[i]);
            }
            for(int i = 1; i <= m; i++) if(rmvd[i] != kas) addEdge(i);
    
            qtot = qct = 0;
            while(c--){
                Cmd &cq = cmd[c];
                if(cq.tp == 'Q') qry(cq.x,cq.p);
                else if(cq.tp == 'C') chgw(cq.x,cq.p);
                else if(cq.tp == 'D')addEdge(cq.x);
            }
            printf("Case %d: %.6lf
    ",kas,qtot/(double)qct);
        }
        return 0;
    }
  • 相关阅读:
    The Levy Flight
    Congestion and Flow Control at the Bundle Layer
    Fragmentation & Reassembly
    six classes of services in delay tolerant networks
    javascript的with表示什么?
    js定时器和计时器
    document.getElementById与getElementByName的区别
    MySQL查询时区分大小写的方法,查询字母出现中文的解决方法
    JavaScript的格式
    地址栏中传递中文参数
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4805297.html
Copyright © 2011-2022 走看看