zoukankan      html  css  js  c++  java
  • BZOJ4388 : JOI2012 invitation

    注意到这个过程实质就是prim算法求最大生成树的过程。

    首先通过离散化+线段树将$A+B$个点缩为上下各$O(n)$个点。

    设已加入集合为$S$,未加入集合为$T$。

    建立两棵线段树,维护所有在$T$集合中的点,以及从每个点连出去的边。

    用一个大根堆维护所有横跨$ST$的边。每次取出堆顶的边,取出与这条边相连的任意一个属于$T$集合的点,若取不出则将这条边删去;否则将这个点加入$S$,并将所有连了它的边加入堆中。

    时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<queue>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>P;
    const int N=100010,M=200010,T=525000,L=2000000;
    int C,n,i,x,y,seq[M];ll ans;bool del[N];
    struct E{int a,b,c,d,t;}e[N];
    priority_queue<P>Q;
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    void NO(){
      puts("-1");
      exit(0);
    }
    inline void umax(int&a,int b){if(a<b)a=b;}
    struct World{
    int n,m,b[N<<1];
    int val[T],g[T],v[L],nxt[L],ed;
    inline int lower(int x){
      int l=1,r=m,mid,t;
      while(l<=r)if(b[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    inline void addx(int x,int y){b[++m]=x;b[++m]=y;}
    void pre(){
      b[++m]=1,b[++m]=n;
      sort(b+1,b+m+1);
      int _m=m;
      m=0;
      for(int i=1;i<=_m;i++)if(b[i]!=b[i-1])b[++m]=b[i];
    }
    inline void find(int&x,int&y){x=lower(x),y=lower(y);}
    void cal(){
      for(int i=1;i<m;i++)if(b[i+1]-b[i]-1){
        if(!seq[i])NO();
        ans+=1LL*seq[i]*(b[i+1]-b[i]-1);
      }
    }
    void build(int x,int a,int b){
      val[x]=b;
      if(a==b)return;
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    void ins(int x,int a,int b,int c,int d,int p){
      if(c<=a&&b<=d){
        v[++ed]=p;nxt[ed]=g[x];g[x]=ed;
        return;
      }
      int mid=(a+b)>>1;
      if(c<=mid)ins(x<<1,a,mid,c,d,p);
      if(d>mid)ins(x<<1|1,mid+1,b,c,d,p);
    }
    int ask(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return val[x];
      int mid=(a+b)>>1,t=0;
      if(c<=mid)t=ask(x<<1,a,mid,c,d);
      if(d>mid)umax(t,ask(x<<1|1,mid+1,b,c,d));
      return t;
    }
    void change(int x,int a,int b,int c){
      for(int&i=g[x];i;i=nxt[i]){
        int j=v[i];
        if(!del[j])Q.push(P(e[j].t,j)),del[j]=1;
      }
      if(a==b){val[x]=0;return;}
      int mid=(a+b)>>1;
      if(c<=mid)change(x<<1,a,mid,c);else change(x<<1|1,mid+1,b,c);
      val[x]=max(val[x<<1],val[x<<1|1]);
    }
    }A,B;
    int v[T];
    void build(int x,int a,int b){
      v[x]=0;
      if(a==b)return;
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
    }
    void change(int x,int a,int b,int c,int d,int p){
      if(c<=a&&b<=d){umax(v[x],p);return;}
      int mid=(a+b)>>1;
      if(c<=mid)change(x<<1,a,mid,c,d,p);
      if(d>mid)change(x<<1|1,mid+1,b,c,d,p);
    }
    void dfs(int x,int a,int b){
      if(a==b){seq[a]=v[x];return;}
      int mid=(a+b)>>1;
      umax(v[x<<1],v[x]),umax(v[x<<1|1],v[x]);
      dfs(x<<1,a,mid),dfs(x<<1|1,mid+1,b);
    }
    int main(){
      read(A.n),read(B.n),read(C),read(n);
      for(i=1;i<=n;i++){
        read(e[i].a),read(e[i].b),read(e[i].c),read(e[i].d),read(e[i].t);
        A.addx(e[i].a,e[i].b);
        B.addx(e[i].c,e[i].d);
      }
      A.pre();
      for(i=1;i<=n;i++)A.find(e[i].a,e[i].b);
      build(1,1,A.m);
      for(i=1;i<=n;i++)if(e[i].a<e[i].b)change(1,1,A.m,e[i].a,e[i].b-1,e[i].t);
      dfs(1,1,A.m);
      A.cal();
      B.pre();
      for(i=1;i<=n;i++)B.find(e[i].c,e[i].d);
      build(1,1,B.m);
      for(i=1;i<=n;i++)if(e[i].c<e[i].d)change(1,1,B.m,e[i].c,e[i].d-1,e[i].t);
      dfs(1,1,B.m);
      B.cal();
      A.build(1,1,A.m);
      B.build(1,1,B.m);
      for(i=1;i<=n;i++){
        A.ins(1,1,A.m,e[i].a,e[i].b,i);
        B.ins(1,1,B.m,e[i].c,e[i].d,i);
      }
      A.change(1,1,A.m,1);
      while(!Q.empty()){
        x=Q.top().second;Q.pop();
        if(y=A.ask(1,1,A.m,e[x].a,e[x].b)){
          ans+=e[x].t;
          A.change(1,1,A.m,y);
          Q.push(P(e[x].t,x));
          continue;
        }
        if(y=B.ask(1,1,B.m,e[x].c,e[x].d)){
          ans+=e[x].t;
          B.change(1,1,B.m,y);
          Q.push(P(e[x].t,x));
          continue;
        }
      }
      if(A.val[1]||B.val[1])NO();
      return printf("%lld",ans),0;
    }
    

      

  • 相关阅读:
    从联想昭阳到MacBook Pro,致我的那些败家玩意——电脑
    讲真,这两款idea插件,能治愈你英语不好的病
    大专学历以后就职会不会有瓶颈
    恕我直言,我怀疑你并不会生成随机数
    一文教会你如何在 Spring 中进行集成测试,太赞了
    30岁开始学编程晚吗?
    delphi下TList的用法
    在Delphi下基于MapWinGIS添加和删除图层标注的方法
    SMS模型格网转换为MIKE21的格网源代码
    样条曲线的Fortran程序
  • 原文地址:https://www.cnblogs.com/clrs97/p/5100395.html
Copyright © 2011-2022 走看看