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

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

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

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

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

时间复杂度$O(n\log 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;
}

  

BZOJ4388 : JOI2012 invitation的更多相关文章

  1. 【BZOJ4388】JOI2012 invitation 堆+线段树+并查集(模拟Prim)

    [BZOJ4388]JOI2012 invitation Description 澳洲猴举办了一场宴会,他想要邀请A个男生和B个女生参加,这A个男生从1到A编号,女生也从1到B编号.现在澳洲猴知道n组 ...

  2. 【JOISC2012 / bzoj4388】Invitation

    Description link Solution 可以发现题目在模拟 Prim 算法求最大生成树的过程,树边故答案与起点 \(C\) 无关. 先把所有区间离散化,注意对于一个区间 \([l,r]\) ...

  3. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  4. BZOJ 4388 [JOI2012春季合宿]Invitation (线段树、二叉堆、最小生成树)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4388 题解 模拟Prim算法? 原题所述的过程就是Prim算法求最大生成树的过程.于是我 ...

  5. HDU 1535 Invitation Cards(最短路 spfa)

    题目链接: 传送门 Invitation Cards Time Limit: 5000MS     Memory Limit: 32768 K Description In the age of te ...

  6. POJ 1511 Invitation Cards (spfa的邻接表)

    Invitation Cards Time Limit : 16000/8000ms (Java/Other)   Memory Limit : 524288/262144K (Java/Other) ...

  7. POJ 1511 Invitation Cards (最短路spfa)

    Invitation Cards 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/J Description In the age ...

  8. HDU1535——Invitation Cards(最短路径:SPAF算法+dijkstra算法)

    Invitation Cards DescriptionIn the age of television, not many people attend theater performances. A ...

  9. Poj 1511 Invitation Cards(spfa)

    Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 24460 Accepted: 8091 De ...

随机推荐

  1. unity3d的四元数 Quaternion

    原地址:http://www.cnblogs.com/88999660/archive/2013/04/02/2995074.html 今天准备学习和研究下unity3d的四元数 Quaternion ...

  2. DICOM:DICOM3.0网络通信协议

    转载:http://blog.csdn.net/zssureqh/article/details/41016091 背景: 专栏取名为DICOM医学图像处理原因是:博主是从医学图像处理算法研究时开始接 ...

  3. HDOJ 1203 I NEED A OFFER!(01背包)

    10397507 2014-03-25 23:30:21 Accepted 1203 0MS 480K 428 B C++ 泽泽 题目链接:http://acm.hdu.edu.cn/showprob ...

  4. linux shell 字符串操作详解 (长度,读取,替换,截取,连接,对比,删除,位置 )

    在做shell批处理程序时候,经常会涉及到字符串相关操作.有很多命令语句,如:awk,sed都可以做字符串各种操作. 其实shell内置一系列操作符号,可以达到类似效果,大家知道,使用内部操作符会省略 ...

  5. 工作中常用shell之ssh登陆不用输入"yes"

    ip="192.168.5.166"ssh $ip -o StrictHostKeyChecking=no           //ssh登陆不用输入"yes" ...

  6. 【云计算】docker build如何支持参数化构建?

    docker 1.9.0版本之后,已经支持docker build参数化构建. docker 版本更新记录: github讨论: 参开资料: https://github.com/docker/doc ...

  7. annotation(@Retention@Target)详解

    一.注解:深入理解JAVA注解 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 1.元注解(meta-a ...

  8. MyBatis3: Could not find SQL statement to include with refid ‘

    错误: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.Incompl ...

  9. iOS 使用interface builder 创建太复杂的constrains时容易产生crash

    今天写程序,遇到了crash,在界面初始化时不会有,想切换到别的tab页就报错了.主要内容如下: Cannot find an outgoing row head for incoming head ...

  10. iOS tableView 选中某个cell时 标准的处理方法

    以前选中cell时,常常判断选中的行数,但是当cell的顺序发生变化时,就要改动处理函数,特别是行数比较多的时候,很麻烦. 之后运用cell的title的内容判断,但是这种判断与现实的内容密切相关,如 ...