题目描述
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) 一个很显然的思路是考虑每个最小值的贡献. 预处理出每个数左边第一个比他小的数,右边第一个比他大的数. 那么\ ...
随机推荐
-
DELPHI与C#语法比较
1.我做了三年的.NET,也是三个月前因为项目需要转的delphi整个过渡差不多要一周到两周.正常情况两周后就能熟悉delphi.delphi可以调整开发环境的,你把他的属性和解决方案窗口调成和你用V ...
-
NYOJ-1070诡异的电梯【Ⅰ】
这道题是个dp,主要考虑两种情况,刚开始我把状态转移方程写成了dp[i] = min(dp[i-1] + a, dp[i + 1] +b); 后来想想当推到dp[i]的时候,那个dp[i + 1]还没 ...
-
R绘图学习笔记(二)-
依照计量对比药物A和药物B的响应情况 #计量向量 dose <- c(20,30,40,45,60) #药物A的反应向量数据 drugA <- c(16,20,27,40,60) #药物B ...
-
1.rs.first()、rs.last()、rs.next()、rs.getRow()
rs.first()获取第一条数据的信息rs.last()获取最后一条数据的信息rs.next()获取下一条数据的信息rs.getRow()获取当前信息的行数 import java.sql.*; p ...
-
termux
使用http服务,链接原服务器要挂vpn. apt edit-sources 如果提示 $ apt edit-sources e: Sub-process editor returned a n er ...
-
IIS出现The specified module could not be found的解决方法
1.打开IIS 信息服务,在左侧找到自己的计算机,点右键,选择属性,在主属性中选编辑,打开“目录安全性”选项卡,单击“匿名访问和验证控制”里的“编辑”按钮,在弹出的对话框中确保只选中了“匿名访问 ...
-
ROS * 了解xacro的编写
在urdf文件中,会有很多内容是一样的,当要改变这些语句重某一个相同的参数时却要更改很多次,很吗发,于是有了一种精简化.可复用.模块化的描述形式——xacro 废话少说 声明重复使用的常量 <? ...
-
Java Web 笔试(面试)题
1.Servlet 的生命周期,并说出 Servlet 与 CGI 的区别 Web 容器加载 Servlet 并将其实例化后,Servlet 生命周期开始,容器运行其 init 方法进行 Servle ...
-
使用原生js实现前端分页功能
背景: 从后台提取出来数据,在前端进行分页. 代码: user-manage.js window.onload = function(){ var result = { message : " ...
-
Zookeeper之Zookeeper的Client的分析
1)几个重要概念 ZooKeeper:客户端入口 Watcher:客户端注册的callback ZooKeeper.SendThread: IO线程 ZooKeeper.EventThread: 事件 ...