• 【BZOJ 1146】[CTSC2008]网络管理Network


    树剖+树状数组套线段树O(nlogn^3)(我打的),有一种更加优秀的算法是O(nlogn^2)的就是直接树状数组套线段树欧拉序(并不快),或者是用主席树维护原始的树的信息,同时用树状数组套线段树维护dfs序上的修改(很优秀),这道题将树上信息转化为序列信息,并在此基础之上用任意树套树,只不过转化的方式不一样,要么是树剖,要么是树上差分(dfs序或者欧拉序都可以)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define mid ((l+r)>>1)
    #define newnode (node+(sz++))
    const int N=80010;
    const int Inf=99999999;
    char xB[(1<<15)+10],*xS=xB,*xTT=xB;
    #define gtc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
    inline void read(int &sum){
        register char ch=gtc();
        for(sum=0;ch<'0'||ch>'9';ch=gtc());
        for(;ch>='0'&&ch<='9';sum=(sum<<1)+(sum<<3)+ch-'0',ch=gtc());
    }
    struct Segment_Tree{
      Segment_Tree *ch[2];
      int size;
    }node[N*150],*add[N],*red[N],*null,*root[N];
    int cnt1,cnt2;
    int n,cnt;
    int val[N];
    struct V{
      int to,next;
    }c[N<<1];
    int head[N],t,sz;
    int ote[N],weight[N],deep[N],size[N];
    int Ti,top[N],dfn[N],id[N];
    inline void Init(){
      null=newnode;
      null->ch[0]=null->ch[1]=null;
      null->size=0;
      for(int i=1;i<=n;++i)root[i]=null;
    }
    inline void U1(Segment_Tree *&p,int l,int r,int pos){
      --p->size;
      if(l==r)return;
      if(pos<=mid)U1(p->ch[0],l,mid,pos);
      else U1(p->ch[1],mid+1,r,pos);
    }
    inline void U2(Segment_Tree *&p,int l,int r,int pos){
      if(p==null)p=newnode,p->ch[0]=p->ch[1]=null,p->size=0;
      ++p->size;
      if(l==r)return;
      if(pos<=mid)U2(p->ch[0],l,mid,pos);
      else U2(p->ch[1],mid+1,r,pos);
    }
    inline int Q(int l,int r,int k){
      if(l==r)return l;
      register int sum=0,i;
      for(i=1;i<=cnt1;++i)
        sum+=add[i]->ch[1]->size;
      for(i=1;i<=cnt2;++i)
        sum-=red[i]->ch[1]->size;
      if(sum>=k){
        for(i=1;i<=cnt1;++i)
          add[i]=add[i]->ch[1];
        for(i=1;i<=cnt2;++i)
          red[i]=red[i]->ch[1];
        return Q(mid+1,r,k);
      }else{
        for(i=1;i<=cnt1;++i)
          add[i]=add[i]->ch[0];
        for(i=1;i<=cnt2;++i)
          red[i]=red[i]->ch[0];
        return Q(l,mid,k-sum);
      }
    }
    inline void Q1(int pos){
      for(;pos>0;pos-=pos&(-pos))
        add[++cnt1]=root[pos],cnt+=root[pos]->size;
    }
    inline void Q2(int pos){
      for(;pos>0;pos-=pos&(-pos))
        red[++cnt2]=root[pos],cnt-=root[pos]->size;
    }
    inline void U(int pos,int val0,int val){
      for(;pos<=n;pos+=pos&(-pos))
        U1(root[pos],0,Inf,val0),U2(root[pos],0,Inf,val);
    }
    inline void U(int pos,int val){
      for(;pos<=n;pos+=pos&(-pos))
        U2(root[pos],0,Inf,val);
    }
    inline void addedge(int x,int y){
      c[++t].to=y,c[t].next=head[x],head[x]=t;
    }
    inline void dfs1(int x,int OPai){
      ote[x]=OPai,deep[x]=deep[OPai]+1;
      size[x]=1;
      for(int i=head[x];i;i=c[i].next)
        if(c[i].to!=OPai){
          dfs1(c[i].to,x);
          size[x]+=size[c[i].to];
          if(size[c[i].to]>size[weight[x]])
            weight[x]=c[i].to;
        }
    }
    inline void dfs2(int x,int tp){
      dfn[x]=++Ti,id[Ti]=x,top[x]=tp;
      if(weight[x]==0)return;
      dfs2(weight[x],tp);
      for(int i=head[x];i;i=c[i].next)
        if(c[i].to!=ote[x]&&c[i].to!=weight[x])
          dfs2(c[i].to,c[i].to);
    }
    inline void Q(int x,int y){
      while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]])std::swap(x,y);
        Q1(dfn[x]),Q2(dfn[top[x]]-1);
        x=ote[top[x]];
      }
      if(deep[x]<deep[y])std::swap(x,y);
      Q1(dfn[x]),Q2(dfn[y]-1);
    }
    int main(){
      int T;
      read(n),read(T),Init();
      for(int i=1;i<=n;++i)read(val[i]);
      for(int i=1,x,y;i<n;++i){
        read(x),read(y);
        addedge(x,y),addedge(y,x);
      }
      dfs1(1,0),dfs2(1,1);
      for(int i=1;i<=n;++i)
        U(dfn[i],val[i]);
      int k,a,b;
      while(T--){
        read(k),read(a),read(b);
        if(k==0){
          U(dfn[a],val[a],b),val[a]=b;
          continue;
        }
        cnt1=cnt2=0;
        cnt=0,Q(a,b);
        if(cnt<k){
          puts("invalid request!");
          continue;
        }
        printf("%d
    ",Q(0,Inf,k));
      }return 0;
    }
  • 相关阅读:
    纯js实现10分钟倒计时
    js中的constructor
    双指放大缩小问题(不需要第三方插件)
    js异步加载的3种方式(转载)
    5种处理js跨域问题方法汇总(转载)
    oncopy="document.selection.empty()"跟oncopy="return false"什么区别?
    十进制 转换为 二进制
    99%的人都理解错了HTTP中GET与POST的区别(转载
    简单封装:检测邮箱是否合法
    Xshell记录日志的方法
  • 原文地址:https://www.cnblogs.com/TSHugh/p/8029911.html
Copyright © 2020-2023  润新知