Description

  link

Solution

  可以发现题目在模拟 Prim 算法求最大生成树的过程,树边故答案与起点 \(C\) 无关。

  先把所有区间离散化,注意对于一个区间 \([l,r]\),要把 \(l,l+1,r\) 三个位置提出来离散化,作为所有新区间的左端点,这样总共只有 \(O(n)\) 个新区间。提 \(l+1\) 的原因待会再说。

  则从起点 \(C\) 出发,寻找所有覆盖 \(C\) 的区间,将这个区间连向的另一个区间扔进大根堆,键值为边权,并删除这个区间。每次取出大根堆堆顶的区间,寻找该区间最左边的一个未被邀请的点,再从该点出发寻找所有覆盖该点的区间,以此类推。

  为什么要把每个区间的左端点单独拆成一个新点(即离散化时要把 \(l+1\) 提出来)呢?考虑这么一种情况:对于一对相连区间,设这对区间中没有子区间,当从外部第一次更新到 这对区间中的某一个区间 时,该区间内的所有点的答案可能不同,即外部先邀请到这对区间的任意一个左端点,然后该左端点借助其和 这对区间中的另一个区间 的连边,经过另一个区间,然后再走若干步,最后回到这个区间时可能会有更大的答案。如果不把左端点拆出来的话,第一次更新到 这对区间中的某一个区间 时,算出来的就是没考虑这对区间的连边时的答案(我们已经假设这对区间中没有子区间,故原来的 \([l,r]\) 区间在离散化后一定是一个点,答案被认为是统一的),所以答案可能会变小。

  然后考虑模拟细节:

    寻找所有覆盖第 \(x\) 个位置的区间。先把所有区间的编号和右端点合为一个二元组 扔到其左端点上,然后把每个点上所有二元组按右端点从大到小排序,查询时枚举第 \(1\) 到 \(x\) 个位置,对每个位置从前往后一直取出并删除二元组,取出所有右端点 \(\ge x\) 的二元组,每个二元组就对应一个覆盖第 \(x\) 个位置的区间。

    查找某个区间 \([l,r]\) 最左边的一个未被邀请的点。用并查集,初始时每个点的父亲都是自己,一个点被邀请则将父亲设为右侧点。这样直接 \(find(l)\) 就找到了。

  复杂度 \(O(n\log n)\)(删除每个区间的最坏时间是 \(O(\log n)\))

#include<bits/stdc++.h>
#define ll long long
const int N = (int)1e5 + 5;
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read(){
int x=0; bool f=1; char c=getchar();
for(;!isdigit(c); c=getchar()) if(c=='-') f=0;
for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
if(f) return x; return 0-x;
}
int A,B,n,cnt,num[N*6],len[N*6],sum; ll ans;
struct info{int l1,r1,l2,r2,v;} a[N];
struct seg{
int l,r,v;
inline bool operator < (const seg& a)const{
return v<a.v;
}
};
priority_queue<seg> Q;
int f[N*6];
int find(int x) {return x==f[x] ? x : f[x]=find(f[x]);}
bool vis[N];
void add_group(int x){
if(vis[x]) return;
vis[x]=1;
Q.push((seg){a[x].l1,a[x].r1,a[x].v}),
Q.push((seg){a[x].l2,a[x].r2,a[x].v});
}
namespace SegTree{
#define ls o<<1
#define rs o<<1|1
vector<pii> vec[N*24];
int s[N*24],p[N*24];
void ins(int o, int l, int r, int x, int v1, int v2){
if(l==r) {vec[o].pb(mp(v1,v2)); return;}
int mid=l+r>>1;
if(x<=mid) ins(ls,l,mid,x,v1,v2);
else ins(rs,mid+1,r,x,v1,v2);
}
inline void pushup(int o) {s[o] = max(s[ls],s[rs]);}
void build(int o, int l, int r){
if(l==r){
if(vec[o].empty()) s[o] = -1;
else
sort(vec[o].begin(),vec[o].end(),greater<pii>()),
s[o] = vec[o][0].fi;
return;
}
int mid=l+r>>1;
build(ls,l,mid), build(rs,mid+1,r);
pushup(o);
}
void mdf(int o, int l, int r, int x){
if(s[o]<x) return;
if(l==r){
while(p[o]<vec[o].size() && vec[o][p[o]].fi>=x) add_group(vec[o][p[o]++].se);
s[o] = (p[o]<vec[o].size() ? vec[o][p[o]].fi : -1);
return;
}
int mid=l+r>>1;
mdf(ls,l,mid,x);
if(x>mid) mdf(rs,mid+1,r,x);
pushup(o);
}
#undef ls
#undef rs
} using namespace SegTree;
void invite(int x, int v){
f[x] = x+1;
mdf(1,1,cnt,x);
sum += len[x];
ans += (ll)len[x]*v;
}
inline int lsh(int x) {return upper_bound(num+1,num+cnt+1,x)-num-1;}
int main(){
A=read(), B=read(), read(), n=read();
for(int i=1; i<=n; ++i){
a[i].l1=read(), a[i].r1=read(), a[i].l2=read()+A, a[i].r2=read()+A, a[i].v=read();
num[++cnt]=a[i].l1, num[++cnt]=a[i].l1+1, num[++cnt]=a[i].r1+1, num[++cnt]=a[i].l2, num[++cnt]=a[i].l2+1, num[++cnt]=a[i].r2+1;
}
num[++cnt]=1, num[++cnt]=2;
sort(num+1,num+cnt+1), cnt=unique(num+1,num+cnt+1)-num-1;
for(int i=1; i<=n; ++i){
a[i].l1 = lsh(a[i].l1),
a[i].r1 = lsh(a[i].r1),
a[i].l2 = lsh(a[i].l2),
a[i].r2 = lsh(a[i].r2);
}
--cnt;
for(int i=1; i<=cnt; ++i) len[i] = num[i+1]-num[i];
for(int i=1; i<=cnt+1; ++i) f[i] = i;
for(int i=1; i<=n; ++i) ins(1,1,cnt,a[i].l1,a[i].r1,i),
ins(1,1,cnt,a[i].l2,a[i].r2,i);
build(1,1,cnt);
invite(1,0); seg tmp; int x;
while(!Q.empty()){
tmp = Q.top(), Q.pop();
x = find(tmp.l);
if(x<=tmp.r) invite(x,tmp.v), Q.push(tmp);
}
if(sum==A+B) printf("%lld\n",ans);
else printf("-1\n");
return 0;
}

【JOISC2012 / bzoj4388】Invitation的更多相关文章

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

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

  2. 【AR实验室】mulberryAR : ORBSLAM2+VVSION

    本文转载请注明出处 —— polobymulberry-博客园 0x00 - 前言 mulberryAR是我业余时间弄的一个AR引擎,目前主要支持单目视觉SLAM+3D渲染,并且支持iOS端,但是该引 ...

  3. 【.net 深呼吸】细说CodeDom(1):结构大观

    CodeDom 是啥东东?Html Dom听过吧,XML Dom听过吧.DOM一般可翻译为 文档对象模型,那 Code + DOM呢,自然是指代码文档模型了.如果你从来没接触过 CodeDom,你大概 ...

  4. 【Machine Learning】KNN算法虹膜图片识别

    K-近邻算法虹膜图片识别实战 作者:白宁超 2017年1月3日18:26:33 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...

  5. 【前端性能】高性能滚动 scroll 及页面渲染优化

    最近在研究页面渲染及web动画的性能问题,以及拜读<CSS SECRET>(CSS揭秘)这本大作. 本文主要想谈谈页面优化之滚动优化. 主要内容包括了为何需要优化滚动事件,滚动与页面渲染的 ...

  6. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  7. 【.net 深呼吸】程序集的热更新

    当一个程序集被加载使用的时候,出于数据的完整性和安全性考虑,程序集文件(在99.9998%的情况下是.dll文件)会被锁定,如果此时你想更新程序集(实际上是替换dll文件),是不可以操作的,这时你得把 ...

  8. 【.net 深呼吸】跨应用程序域执行程序集

    应用程序域,你在网上可以查到它的定义,凡是概念性的东西,大伙儿只需要会搜索就行,内容看了就罢,不用去记忆,更不用去背,“名词解释”是大学考试里面最无聊最没水平的题型. 简单地说,应用程序域让你可以在一 ...

  9. 【Web动画】SVG 实现复杂线条动画

    在上一篇文章中,我们初步实现了一些利用基本图形就能完成的线条动画: [Web动画]SVG 线条动画入门 当然,事物都是朝着熵增焓减的方向发展的,复杂线条也肯定比有序线条要多. 很多时候,我们无法人工去 ...

随机推荐

  1. 【转】TCP/IP网络协议各层首部

    ​ 数据包封装流程(逐层封装,逐层解封) 二层帧(二层帧中目的地址6个字节,源地址6个字节,长度/类型2个字节,二层帧共18个字节) ip头部(ip头部20字节) tcp头部(tcp头部20个字节): ...

  2. linux中文件权限的字母含义

    一.文件系统部分 - 普通文件(文本文件,二进制文件,压缩文件,电影,图片...)d 目录文件(蓝色)b 设备文件(块设备)存储设备硬盘,U盘 /dev/sda, /dev/sda1c 设备文件(字符 ...

  3. C#实现多线程的方式:Task——任务

    简介 .NET 4包含新名称空间System.Threading.Tasks,它 包含的类抽象出了线程功能. 在后台使用ThreadPool. 任务表示应完成的某个单元的工作. 这个单元的工作可以在单 ...

  4. 前端ajax中运用post请求和get请求之于session验证

    首先我们来看下ajax两种请求的区别: Ajax中POST和GET的区别Get和Post都是向服务器发送的一种请求,只是发送机制不同. 1. GET请求会将参数跟在URL后进行传递,而POST请求则是 ...

  5. javascript学习笔记 BOM和DOM详解

    js组成 我们都知道, javascript 有三部分构成,ECMAScript,DOM和BOM,根据宿主(浏览器)的不同,具体的表现形式也不尽相同,ie和其他的浏览器风格迥异. 1. DOM 是 W ...

  6. [转帖]Mysql binlog 介绍

    binlog介绍   1.什么是binlog binlog是一个二进制格式的文件,用于记录用户对数据库更新的SQL语句信息,例如更改数据库表和更改内容的SQL语句都会记录到binlog里,但是对库表等 ...

  7. idea启动tomcat时报错:Error during artifact deployment. See server log for details.

    Error during artifact deployment. See server log for details. 这个很多人都找不出来,原因无非2个: 一.jar 包有有些没能识别,tomc ...

  8. 【AtCoder】AGC003

    AGC编号越小越水???? AGC003 A - Wanna go back home 相对方向要么一起有要么一起没有 #include <bits/stdc++.h> #define f ...

  9. Netty源码剖析-启动服务

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! --1主线分两步: 一:首先在our thread里,如果写在mai ...

  10. axios拦截器的介绍

    interceptors 拦截器 拦截器一般做什么? 1. 修改请求头的一些配置项 2. 给请求的过程添加一些请求的图标 3. 给请求添加参数 拦截器的基本语法: 拦截器分为全局拦截器和局部拦截器 全 ...