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) 一个很显然的思路是考虑每个最小值的贡献. 预处理出每个数左边第一个比他小的数,右边第一个比他大的数. 那么\ ...
随机推荐
- Centos/Rhel7部署Zabbix监控(部署篇之服务器篇)
Zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. Zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员快速定位/解决 ...
- [国嵌笔记][031][Bootloader架构设计]
- 自己编写JavaScript的sort函数
在平常开发中我们经常会遇到对数组进行排序的场景,js给我们提供了sort方法可以对数组元素进行排序,默认是按ASCII字母表顺序排序,请看下面例子: var a = [1, 3, 2, 4];var ...
- windows平台下python 打包成exe可执行文件
第一步 安装 pyinstaller 命令行下运行:pip install pyinstaller 第二步 打包安装 pyinstaller Test.py 第三步 完成 找到打包目录下dist目录 ...
- 久未更 ~ 五之 —— 引入外部CSS样式表 小节
> > > > > 久未更 系列一:在html中引入外部css样式表 //引入外部css样式表 //<lilnk>要放在<head>标签的第一行, ...
- css样式小记
溢出文字展现为... .over-hidd { white-space: nowrap; text-overflow: ellipsis; overflow: hidden; }
- 为什么要进行URL编码
我们都知道Http协议中参数的传输是"key=value"这种简直对形式的,如果要传多个参数就需要用“&”符号对键值对进行分割.如"?name1=value1&a ...
- asp.net -mvc框架复习(2)-创建ASP.NET MVC 第一个程序以及MVC项目文件夹说明
建议vs2013或2013以上版本的vs,要是跨平台的话最好用vs2015或vs2017的asp.net mvc core . 1.创建ASP.NET MVC 第一个程序 打开vs2013->文 ...
- J.U.C JMM. pipeline.指令重排序,happen-before(续)
前面已经介绍硬件平台Cache Coherence问题和解决办法,下面来看看Java虚拟机平台的相关知识.硬件平台处理器,高速缓存,主存之间的交互关系如下: Java内存模型(JMM) ...
- Java泛型类和泛型方法
java编程思想说道: 泛型类是应用在整个类上,但同时可以在类中包含参数化方法,而这个方法所在的类可以是泛型,也可以不是泛型,也就是说是否有泛型方法,与其所在的类是否是泛型类没有关系. 泛型方法是的该 ...