zoukankan      html  css  js  c++  java
  • 【BZOJ 1146】【CTSC 2008】网络管理network

    一句话题意,树链上带改动区间第k大
    感觉能够dfs+主席树O(nlog2n)过掉,但我不会写= =
    于是写的线段树套平衡树+链剖+二分(改动O(nlog3n),查询O(nlog4n)慢了好多啊QAQ)
    这里简介一下区间第K大做法。对于每一个线段树所”管辖“的范围,建一棵相应范围内的平衡树(我用的Treap);改动时,改动每一个包括被改动节点的线段树节点所相应的Treap。查询时。二分
    答案。统计每一个区间内比当前答案小的数就可以(为了保证是序列里的数。我们能够二分答案在原序列中排名)
    PS:这题真的是第K大,不是排名第K的,被坑WA了一次= =
    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mid (l+r)/2
    #define lch i<<1,l,mid
    #define rch i<<1|1,mid+1,r
    using namespace std;
    struct treap_node{
        treap_node *left,*right;
        int val,fix,size,wgt;
        treap_node(int val): val(val) {size=1; wgt=1; left=right=NULL; fix=rand();}
        int lsize()
          {if (left) return left->size; else return 0;}
        int rsize()
          {if (right) return right->size; else return 0;}
        void Maintain()
          {size=wgt; size+=lsize()+rsize();}
    };
    treap_node *seg[320001];
    int f[80001],plc[80001];
    int point[80001],next[200001];
    struct hp{
        int u,v;
    }ai[200001];
    struct hq{
        int dep,fat,top,size,wson;
    }tree[80001];
    int n,a[80001],ans,m,totw,e=0;
    void tlr(treap_node *&a)
    {
        treap_node *b=a->right;
        a->right=b->left; b->left=a;
        a->Maintain(); b->Maintain(); a=b;
    }
    void trr(treap_node *&a)
    {
        treap_node *b=a->left;
        a->left=b->right; b->right=a;
        a->Maintain(); b->Maintain(); a=b;
    }
    void add(int u,int v)
    {
        e++; ai[e].u=u; ai[e].v=v; next[e]=point[u]; point[u]=e;
        e++; ai[e].v=u; ai[e].v=u; next[e]=point[v]; point[v]=e;
    }
    void insert(treap_node *&p,int value)  
    {  
        if (!p)  
          p=new treap_node(value);  
        else  
          {  
            if (value==p->val)  
              p->wgt++;  
            if (value<p->val)  
              {  
                insert(p->left,value);  
                if (p->left->fix<p->fix)  
                  trr(p);  
              }  
            if (value>p->val)  
              {  
                insert(p->right,value);  
                if (p->right->fix<p->fix)  
                  tlr(p);  
              }  
          }  
        p->Maintain();  
    }
    void make_node(int i,int l,int r)
    {
        int j;
        for (j=l;j<=r;++j)
          insert(seg[i],a[f[j]]);
    }
    void build(int i,int l,int r)
    {
        make_node(i,l,r);
        if (l==r) return;
        build(lch); build(rch);
    }
    void build_tree(int now,int last,int depth)
    {
        int i;
        tree[now].fat=last;
        tree[now].dep=depth;
        tree[now].size=1;
        tree[now].wson=0;
        for (i=point[now];i;i=next[i])
          if (ai[i].v!=last)
            {
              build_tree(ai[i].v,now,depth+1);
              tree[now].size+=tree[ai[i].v].size;
              if (tree[ai[i].v].size>tree[tree[now].wson].size)
                tree[now].wson=ai[i].v;
            }
    }
    void build_seg(int now,int tp)
    {
        int i;
        tree[now].top=tp;
        plc[now]=++totw; f[totw]=now;
        if (tree[now].wson!=0)
          build_seg(tree[now].wson,tp);
        for (i=point[now];i;i=next[i])
          if (ai[i].v!=tree[now].wson&&ai[i].v!=tree[now].fat)
            build_seg(ai[i].v,ai[i].v);
    }
    void del(treap_node *&p,int val)
    {
        if (val==p->val)
          {
            if (p->wgt==1)
              {
                if (!p->left||!p->right)
                  {
                    if (!p->left) p=p->right;
                    else p=p->left;
                  }
                else
                  {
                    if (p->left->fix<p->right->fix)
                      {trr(p); del(p->right,val);}
                    else
                      {tlr(p); del(p->left,val);}
                  }
              }
            else
              p->wgt--;
          }
        else
          {
            if (val<p->val) del(p->left,val);
            else del(p->right,val);
          }
        if (p!=NULL) p->Maintain(); 
    }
    int kth(treap_node *p,int k)
    {
        if (k<=p->lsize()) return kth(p->left,k);
        if (k>p->lsize()+p->wgt) return kth(p->right,k-p->lsize()-p->wgt);
        if (k<=p->lsize()+p->wgt) return p->val;
    }
    int rank(treap_node *p,int val,int cur)
    {
        if (val==p->val) return cur+p->lsize();
        if (val>p->val&&!p->right) return cur+p->lsize()+p->wgt;
        if (val<p->val&&!p->left) return cur;
        if (val<p->val) return rank(p->left,val,cur);
        if (val>p->val) return rank(p->right,val,cur+p->lsize()+p->wgt);
    }
    void query(int i,int l,int r,int x,int y,int val)
    {
        if (x<=l&&y>=r)
          {
            ans+=rank(seg[i],val,0);
            return;  
          }
        if (x<=mid) query(lch,x,y,val);
        if (y>mid) query(rch,x,y,val);
    }
    void delt(int i,int l,int r,int x,int num)
    {
        if (l==x&&l==r)
          {
            del(seg[i],num);
            return;
          }
        del(seg[i],num);
        if (x<=mid) delt(lch,x,num);
        else delt(rch,x,num);
    }
    void ins(int i,int l,int r,int x,int num)
    {
        if (l==x&&l==r)
          {
            insert(seg[i],num);
            return;
          }
        insert(seg[i],num);
        if (x<=mid) ins(lch,x,num);
        else ins(rch,x,num);
    }
    int Qsum(int x,int y)
    {
        int t=0,f1=tree[x].top,f2=tree[y].top;
        while (f1!=f2)
          {
            //cout<<x<<' '<<y<<' '<<f1<<' '<<f2<<endl;
            if (tree[f1].dep<tree[f2].dep) {swap(x,y); swap(f1,f2);}
            t+=plc[x]-plc[f1]+1;
            x=tree[f1].fat; f1=tree[x].top;
          }
        if (tree[x].dep>tree[y].dep) swap(x,y);
        t+=plc[y]-plc[x]+1;
        return t;
    }
    void Q(int x,int y,int num)
    {
        int f1=tree[x].top,f2=tree[y].top;
        while (f1!=f2)
          {
            if (tree[f1].dep<tree[f2].dep) {swap(x,y); swap(f1,f2);}
            query(1,1,n,plc[f1],plc[x],num);
            x=tree[f1].fat; f1=tree[x].top;
          } 
        if (tree[x].dep>tree[y].dep) swap(x,y);
        query(1,1,n,plc[x],plc[y],num);
    }
    void work(int x,int y,int k)
    {
        int l,r,t,midx,len;
        l=1; r=n;
        len=Qsum(x,y);
        if (k>len) {printf("invalid request!
    "); return;}
        k=len-k+1;
        while (l<r)
          {
            midx=(l+r+1)/2;
            t=kth(seg[1],midx);
            ans=0; Q(x,y,t);
            if (ans<=k-1) l=midx;
            else r=midx-1;
          }
        printf("%d
    ",kth(seg[1],l));
    }
    int main()
    {
        int i,x,y,k;
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;++i)
          scanf("%d",&a[i]);
        for (i=1;i<n;++i)
          {
            scanf("%d%d",&x,&y);
            add(x,y);
          }
        build_tree(1,0,0);
        build_seg(1,1);
        build(1,1,n);
        for (i=1;i<=m;++i)
          {
            scanf("%d%d%d",&k,&x,&y);
            if (k==0)
              {
                delt(1,1,n,plc[x],a[x]);
                ins(1,1,n,plc[x],y);
                a[x]=y; 
              }
            if (k>0)
              work(x,y,k);
          }
    }
  • 相关阅读:
    Linux libcurl使用 (收藏)
    公钥和私钥与认证和签名
    fedora下配置ipv6 dns服务器
    SHA1
    linux IP 命令
    SSL/TLS协议簇加解密流程
    MD5算法实现原理
    container_of深入理解
    diff和patch使用指南
    oracle 笔记
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/7105767.html
Copyright © 2011-2022 走看看