D 洛谷 P3602 Koishi Loves Segments [贪心 树状数组+堆]
题目描述
Koishi喜欢线段。
她的条线段都能表示成数轴上的某个闭区间
。Koishi喜欢在把所有线段都放在数轴上,然后数出某些点被多少线段覆盖了。
Flandre看她和线段玩得很起开心,就抛给她一个问题:
数轴上有个点突然兴奋,如果自己被身上覆盖了超过
条线段,这个点就会浑身难受然后把Koishi批判一番。
Koishi十分善良,为了不让数轴上的点浑身难受,也为了让自己开心,她想在数轴上放入尽量多的线段。
按照套路,Koishi假装自己并不会做这道题,所以她就来求你帮忙。并承诺如果你解决了问题就给你打一通电话w。
输入输出格式
输入格式:
第一行两个个整数,分别表示插入的线段数和关键点数。
接下来行,每行两个整数
,表示线段
的端点。
接下来行,每行两个整数
,表示有个位于
的点突然兴奋,并认为自己身上不得覆盖超过
条线段
输出格式:
一个整数,表示最多能放入的线段数
输入输出样例
4 3
1 3
2 4
5 7
6 8
2 5
3 1
6 2
3
说明
对于20%的数据,满足
对于60%的数据,满足
对于80%的数据,满足
对于100%的数据,满足
如果一个点兴奋了两次,那么Koishi应当满足它的*较严苛的要求*(也就是相同时
取最小值啦)
请适当使用读入优化
比赛时交了一个网络流60分
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=,M=1e6,INF=1e9;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,m,s,t;
struct rec{
int l,r;
}a[N];
struct point{
int p,k;
bool operator <(const point a)const{
if(p==a.p) return k<a.k;
else return p<a.p;
}
}b[N]; struct edge{
int v,c,f,ne;
}e[M<<];
int cnt,h[N];
inline void ins(int u,int v,int c){
cnt++;
e[cnt].v=v;e[cnt].c=c;e[cnt].f=;e[cnt].ne=h[u];h[u]=cnt;
cnt++;
e[cnt].v=u;e[cnt].c=;e[cnt].f=;e[cnt].ne=h[v];h[v]=cnt;
}
int cur[N],d[N],vis[N];
int q[N],head,tail;
bool bfs(){
head=tail=;
memset(vis,,sizeof(vis));
d[s]=;vis[s]=;q[tail++]=s;
while(head!=tail){
int u=q[head++];
for(int i=h[u];i;i=e[i].ne){
int v=e[i].v;
if(!vis[v]&&e[i].c>e[i].f){
vis[v]=;d[v]=d[u]+;
q[tail++]=v;
if(v==t) return true;
}
}
}
return false;
}
int dfs(int u,int a){
if(u==t||a==) return a;
int flow=,f;
for(int &i=cur[u];i;i=e[i].ne){
int v=e[i].v;
if(d[v]==d[u]+&&(f=dfs(v,min(e[i].c-e[i].f,a)))>){
flow+=f;
e[i].f+=f;
e[((i-)^)+].f-=f;
a-=f;
if(a==) break;
}
}
if(a) d[u]=-;
return flow;
}
int dinic(){
int flow=;
while(bfs()){
for(int i=s;i<=t;i++) cur[i]=h[i];
flow+=dfs(s,INF);
}
return flow;
}
//int Bin(int v){
// int l=1,r=m;
// while(l<r){
// int mid=(l+r)>>1;
// if(v<=b[mid].p) r=mid;
// else if(v>b[mid].p) l=mid+1;
// }
// return l;
//} void buildGraph(){
for(int i=;i<=m;i++) ins(n+n+i,n+n+m+i,b[i].k);
for(int i=;i<=n;i++){
ins(s,i,);ins(n+i,t,);
int now=i;
for(int j=;j<=m;j++){
if(b[j].p<a[i].l) continue;
if(b[j].p>a[i].r) break;
ins(now,n+n+j,);
now=n+n+m+j;
}
ins(now,n+i,);
}
}
void getMP(){
sort(b+,b++n);
int p=;b[++p]=b[];
for(int i=;i<=m;i++)
if(b[i].p!=b[i-].p) b[++p]=b[i];
m=p;
}
int main(int argc, const char * argv[]){
n=read();m=read();
for(int i=;i<=n;i++) a[i].l=read(),a[i].r=read();
for(int i=;i<=m;i++) b[i].p=read(),b[i].k=read();
getMP();s=;t=n+n+m+m+;
buildGraph();
printf("%d",dinic());
return ;
}
网络流
正解是贪心 从左到右考虑每一个点和线段 这个点不满足条件就删除覆盖它的且r最大的线段
实现起来有好多做法,标程用了set维护覆盖当前考虑点的所有线段
好多人用了线段树(和矩形面积并类似),然而并不明白它们怎么找的线段
其实加减线段 询问一个点覆盖次数直接差分后用树状数组就好了.....然后用一个堆维护当前加入的所有线段为了取出r最大的线段
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
const int N=4e5+,M=1e6+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,m;
int mp[M];
void iniMP(){
sort(mp+,mp++mp[]);
int p=;
mp[++p]=mp[];
for(int i=;i<=mp[];i++) if(mp[i]!=mp[i-]) mp[++p]=mp[i];
mp[]=p;
}
inline int Bin(int v){
int l=,r=mp[];
while(l<=r){
int mid=(l+r)>>;
if(v==mp[mid]) return mid;
else if(v<mp[mid]) r=mid-;
else l=mid+;
}
return ;
} int c[M];
inline int lowbit(int x){return x&-x;}
inline void add(int p,int v){for(;p<=mp[];p+=lowbit(p)) c[p]+=v;}
inline int sum(int p){
int re=;
for(;p>;p-=lowbit(p)) re+=c[p];
return re;
}
struct Segment{
int l,r;
bool operator <(const Segment &a)const{return l<a.l;}
}s[N];
struct Point{
int p,x;
bool operator <(const Point &a)const{return p<a.p;}
}a[N];
struct Node{
int r,id;
bool operator <(const Node &a)const{return r<a.r;}
Node(int a=,int b=):r(a),id(b){}
};
priority_queue<Node> q;
int ans;
void solve(){
for(int i=;i<=n;i++) s[i].l=Bin(s[i].l),s[i].r=Bin(s[i].r);
for(int i=;i<=m;i++) a[i].p=Bin(a[i].p);
sort(s+,s++n);
sort(a+,a++m);
for(int i=,j=;i<=m;i++){
for(;j<=n&&s[j].l<=a[i].p;j++){
add(s[j].l,);
add(s[j].r,-);
q.push(Node(s[j].r,j));ans++;
}
while(sum(a[i].p)>a[i].x){
int x=q.top().id; q.pop();ans--;
add(s[x].l,-);
add(s[x].r,);
}
}
printf("%d",ans);
}
int main(int argc, const char * argv[]){
n=read();m=read();
for(int i=;i<=n;i++)
mp[++mp[]]=s[i].l=read(),mp[++mp[]]=s[i].r=read()+; for(int i=;i<=m;i++)
mp[++mp[]]=a[i].p=read(),a[i].x=read();
iniMP();
solve();
return ;
}
D 洛谷 P3602 Koishi Loves Segments [贪心 树状数组+堆]的更多相关文章
- 洛谷P3602 Koishi Loves Segments 贪心
		
正解:贪心 解题报告: 传送门! 首先在学习贪心的入门题的时候我们就知道,当x=1的时候,也就是每条线段不能相交的时候的做法——就按右端点排序然后能选就选,也就是会议安排问题,原因显然?就你选右端点更 ...
 - 洛谷P3602 Koishi Loves Segments(贪心,multiset)
		
洛谷题目传送门 贪心小水题. 把线段按左端点从小到大排序,限制点也是从小到大排序,然后一起扫一遍. 对于每一个限制点实时维护覆盖它的所有线段,如果超过限制,则贪心地把右端点最大的线段永远删去,不计入答 ...
 - [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)
		
[NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...
 - 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)
		
洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...
 - BZOJ3262/洛谷P3810 陌上花开 分治 三维偏序 树状数组
		
原文链接http://www.cnblogs.com/zhouzhendong/p/8672131.html 题目传送门 - BZOJ3262 题目传送门 - 洛谷P3810 题意 有$n$个元素,第 ...
 - 洛谷 P4396 (离散化+莫队+树状数组)
		
### 洛谷P4396 题目链接 ### 题目大意: 有 n 个整数组成的数组,m 次询问,每次询问中有四个参数 l ,r,a,b .问你在[l,r] 的区间内的所有数中,值属于[a,b] 的数的个 ...
 - [P4064][JXOI2017]加法(贪心+树状数组+堆)
		
题目描述 可怜有一个长度为 n 的正整数序列 A,但是她觉得 A 中的数字太小了,这让她很不开心. 于是她选择了 m 个区间 [li, ri] 和两个正整数 a, k.她打算从这 m 个区间里选出恰好 ...
 - 【题解】洛谷P1966 [NOIP2013TG] 火柴排队(树状数组+逆序对)
		
次元传送门:洛谷P1966 思路 显然在两排中 每排第i小的分别对应就可取得最小值(对此不给予证明懒) 所以我们只在意两排的火柴是第几根 高度只需要用来进行排序(先把两个序列改成有序的方便离散化) 因 ...
 - 洛谷P3246 [HNOI2016]序列(离线 差分 树状数组)
		
题意 题目链接 Sol 好像搞出了一个和题解不一样的做法(然而我考场上没写出来还是爆零0) 一个很显然的思路是考虑每个最小值的贡献. 预处理出每个数左边第一个比他小的数,右边第一个比他大的数. 那么\ ...
 
随机推荐
- 微信小程序实现滚动加载更多
			
1.需要用到的组件和api scroll-view(可滚动视图区域) wx.showToast(OBJECT)显示消息提示窗----显示loading小菊花用的 2.需要用到的属性 3.scrol-v ...
 - JXLS 2.4.0系列教程(四)——多sheet是怎么做到的
			
注:本文代码在第一篇文章基础上修改而成,请务必先阅读第一篇文章. http://www.cnblogs.com/foxlee1024/p/7616987.html 本文也不会过多的讲解模板中遍历表达式 ...
 - UEP-查询方式总结
			
public void retrieve() { QueryParamList params = getQueryParam("dataWrap"); //获取页面上的参数,即查询 ...
 - 【shell mysql 导出数据到csv脚本,完美解决乱码转义符等问题】-费元星
			
#!/bin/bash#@author:feiyuanxing [既然笨到家,就要努力到家]#@date:2017-12-05#@E-Mail:feiyuanxing@gmail.com#@TARGE ...
 - dedecms中{dede:myad name='about'/} 修改内容
			
网站首页index.htm中调用这个命令,显示一段文字,但是想要修改内容.所以想知道这个命令指定的文件内容在哪里寻找或者指定内容在哪里修改? 匿名 | 浏览 6036 次 发布于2014-02-19 ...
 - 引导图滤波(Guided Image Filtering)原理以及OpenCV实现
			
引导图是一种自适应权重滤波器,能够在平滑图像的同时起到保持边界的作用,具体公式推导请查阅原文献<Guided Image Filtering>.这里只说一下自适应权重原理.C++实现灰度图 ...
 - Swift2
			
Swift 里的数组和字典虽然都是结构体(struct),但在参数传递过程中处理方式却不一样,默认 Array 是引用传递,Dictionary 是值传递.而在 Java 中,由于数组和 Map 都是 ...
 - 一天浓缩学习webpack经过
			
熟话说浓缩就是精华,哈哈,所以就这么简单粗暴的介绍下吧,写下的都是精华. 已经不是第一次听说webpack,但是我的起步有点晚,现在才看.开门见山~~ 1.什么是webpack? webpack是当下 ...
 - AF_INET 和PF_INET区别;AF_LOCAL PF_LOCAL 区别.
			
从字面理解: AF_INET = Address Format, Internet = IP Addresses PF_INET = Packet Format, Internet = IP, TCP ...
 - php 利用Gd库添加文字水印乱码的问题及解决方案
			
最近一个项目进行了服务器迁移,部署后发现 ,其中一个为图片添加水印文字的功能出现了乱码问题,确认功能代码不存在问题,同时项目代码都是使用UTF-8编码,不存在编码问题,也检查排除了字体文件出现问题的可 ...