题面

CF1389F Bicolored Segments

给 \(n\) 条线段 \([l_i,r_i]\),每条有个颜色 \(t_i\in\{0,1\}\),求最多选出多少条线段,使没有不同颜色的线段相交。

数据范围:\(1\le n\le 2\cdot 10^5\),\(1\le l_i\le r_i\le 10^9\)。


蒟蒻语

昨天蒟蒻打 CF,发挥得不错,迷惑回橙。但是蒟蒻没做出这题,赛后想了好久感觉这题很奇妙,于是蒻蒻地来写篇题解。


蒟蒻解一

线段树维护 dp。

先将每条线段 \(l_i,r_i\) 离散化,坐标范围为 \([0,cnt]\)。

设 \(f(i,j,k)\) 表示看了 \([0,i]\),\([j+1,i]\) 的线段颜色都为 \(k\) 的最多线段数。

\[j<i:f(i,j,k)=f(i-1,j,k)+\sum_{x=1}^{n}[l_x>j][r_x=i]
\]
\[f(i,i,k)=\max[\max_{j=0}^{i-1}f(i,j,!k),\max_{j=0}^{i-1}f(i,j,k)]
\]

那么答案是 \(\max_{j=0}^{cnt}f(cnt,j,0/1)\)。

设 \(ca_i\) 这个 vector 存放 \(r_x=i\) 的 \(x\)。

所以可以用一个线段树代替 \(j\) 维,把 \(i\) 维滚掉,实现上述dp。

时间复杂度 \(\Theta(n\log n)\)。

代码

#include <bits/stdc++.h>
using namespace std; //Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair(a,b)
#define x first
#define y second
#define be(a) a.begin()
#define en(a) a.end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f; //Data
const int N=2e5,M=(N<<1)+1;
int n,l[N],r[N],t[N],cnt,b[M],ans;
vector<int> ca[M]; //Segmenttree
const int T=M<<2;
#define lk k<<1
#define rk k<<1|1
struct Segmenttree{ //线段树,下标为坐标,维护区间加、全局最大值
int mx[T],mk[T];
void pushup(int k){mx[k]=max(mx[lk],mx[rk]);}
void pm(int k,int v){mk[k]+=v,mx[k]+=v;}
void pushdown(int k){if(mk[k]) pm(lk,mk[k]),pm(rk,mk[k]),mk[k]=0;}
void fix(int x,int y,int v,int k,int l,int r){
if(x<=l&&r<=y) return pm(k,v);
pushdown(k);
int mid=(l+r)>>1;
if(mid>=x) fix(x,y,v,lk,l,mid);
if(mid<y) fix(x,y,v,rk,mid+1,r);
pushup(k);
}
int Mx(){return mx[1];}
void Print(int k,int l,int r){
if(l==r){cout<<mx[k]<<' ';return;}
pushdown(k);
int mid=(l+r)>>1;
Print(lk,l,mid),Print(rk,mid+1,r);
}
}g[2]; //Main
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=0;i<n;i++){
cin>>l[i]>>r[i]>>t[i],--t[i];
b[cnt++]=l[i],b[cnt++]=r[i];
}
b[cnt++]=0,sort(b,b+cnt),cnt=unique(b,b+cnt)-b;
for(int i=0;i<n;i++){
l[i]=lower_bound(b,b+cnt,l[i])-b;
r[i]=lower_bound(b,b+cnt,r[i])-b;
ca[r[i]].pb(i);
}
for(int i=1;i<cnt;i++){
for(int x:ca[i]) g[t[x]].fix(0,l[x]-1,1,1,0,cnt);
g[0].fix(i,i,g[1].Mx(),1,0,cnt),g[1].fix(i,i,g[0].Mx(),1,0,cnt);//这么写也是可以的
}
cout<<max(g[0].Mx(),g[1].Mx())<<'\n';
return 0;
}

蒟蒻解二

萌新初学 OI 的时候,有一个贪心问题:求最多线段互不相交。做法是右端点再左端点双关键字排序,然后贪心取舍一下。

这题可以同样地骚操作:

初始化答案为 \(n\)。用两个 multiset 记录两种颜色分别选了哪些线段。

顺序枚举排序了的线段,如果没有选了的线段与当前线段异色并重合,那么蒟蒻们可以很开心地选上这条线段。

否则把右端点在当前线段左端点右边并且最近的异色线段从 multiset 中删除,不往 multiset 中加入当前线段,把答案 \(-1\),表示一个对抗抵消的过程。

比如加了一条 \(0\) 线段,然后再加一条 \(1\) 线段与它抵消。这时如果来 \(2\) 条 \(1\) 线段,相当于选了 \(3\) 条 \(1\) 线段;如果来 \(2\) 条 \(0\) 线段,相当于选了 \(3\) 条 \(0\) 线段。

这种思想类似求序列众数时的对抗抵消选举和模拟网络流反悔推流。

时间复杂度 \(\Theta(n\log n)\)。

代码

#include <bits/stdc++.h>
using namespace std; //Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair(a,b)
#define x first
#define y second
#define be(a) a.begin()
#define en(a) a.end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f; //Data
const int N=2e5;
int n,ans;
struct S{int l,r,t;}a[N];
multiset<int> g[2]; //Main
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n,ans=n;
for(int i=0;i<n;i++)
cin>>a[i].l>>a[i].r>>a[i].t,--a[i].t;
sort(a,a+n,[&](const S p,const S q){return p.r==q.r?p.l<q.l:p.r<q.r;});
for(int i=0;i<n;i++)
if(g[!a[i].t].lower_bound(a[i].l)==en(g[!a[i].t])) g[a[i].t].insert(a[i].r);
else ans--,g[!a[i].t].erase(g[!a[i].t].lower_bound(a[i].l));
cout<<ans<<'\n';
return 0;
}

祝大家学习愉快!

题解-CF1389F Bicolored Segments的更多相关文章

  1. Codeforces Educational Round 92 赛后解题报告(A-G)

    Codeforces Educational Round 92 赛后解题报告 惨 huayucaiji 惨 A. LCM Problem 赛前:A题嘛,总归简单的咯 赛后:A题这种**题居然想了20m ...

  2. CodeForces 430A Points and Segments (easy)(构造)题解

    题意:之前愣是没看懂题意...就是给你n个点的坐标xi,然后还规定了Li,Ri,要求给每个点染色,每一组L,R内的点红色和黑色的个数不能相差大于1个,问你能不能染成功,不能输出-1,能就按照输入的顺序 ...

  3. LeetCode题解之Number of Segments in a String

    1.题目描述 2.题目分析 找到字符串中的空格即可 3.代码 int countSegments(string s) { ){ ; } vector<string> v; ; i < ...

  4. PAT甲题题解-1104. Sum of Number Segments (20)-(水题)

    #include <iostream> #include <cstdio> #include <algorithm> #include <string.h&g ...

  5. POJ3304:Segments——题解

    http://poj.org/problem?id=3304 题目大意:给n条线段,求是否存在一条直线,将所有线段投影到上面,使得所有投影至少交于一点. ——————————————————————— ...

  6. [CF1167D]Bicolored RBS题解

    模拟两个颜色的扩号层数,贪心,如果是左括号,哪边的层数浅就放那边:如果是右括号,哪边的层数深就放那边. 至于层数的维护,两个int就做掉了 放个代码: #include <cstdio> ...

  7. [CF846C]Four Segments题解

    我们暴力枚举一下\(delim_{1}\) 然后对于每个\(delim_{1}\),O(n)扫一遍+前缀和求出最大\(delim_{0}\)和\(delim_{2}\),然后记录一下它们的位置就行啦 ...

  8. 【题解】CF1426D Non-zero Segments

    题目戳我 \(\text{Solution:}\) 若\([l,r]\)子段和是\(0,\)则\(sum[r]=sum[l-1].\) 于是我们可以考虑维护当前哪一个前缀和出现过.对于区间\([l,r ...

  9. Codeforces Round #337 (Div. 2) D. Vika and Segments 线段树 矩阵面积并

    D. Vika and Segments     Vika has an infinite sheet of squared paper. Initially all squares are whit ...

随机推荐

  1. linx mysql安装

    文章引用:https://www.cnblogs.com/shizhongyang/p/8464876.html 只做了少量修改,感谢博主 注:未防止混淆,这里都用绝对路径执行命令 除了文件内容中的# ...

  2. //*[starts-with(@class,'btn')][text()='差'] 正则定位元素

    starts-with?  //*[starts-with(@class,'btn')][text()='差']   意思找从头开始的这个class

  3. 深度解读最新版 Scrum 指南

    本文作者:CODING - 敏杰小王子 11 月 18 日晚,Scrum 框架的创始人 Jeff Sutherland 和 Ken Schwaber 联手发布了最新版 Scrum 指南.作为 Scru ...

  4. Linux(centos6.8)配置Mysql环境

    1.下载mysql安装包 https://downloads.mysql.com/archives/community/ 2.查询mysql信息 [1]查询mysql是否已经安装 [root@plut ...

  5. LeetCode 中等题解(4)

    40 组合总和 II Question 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates ...

  6. 免费|申请谷歌云服务器|msf安装

    apt-get install -y wget 参考链接 知乎-免费|申请谷歌云服务器 知乎-免费|申请谷歌云服务器 cnblogs-debian.ubuntu安装metasploit通用方法 谷歌云 ...

  7. webug第一关:很简单的一个注入

    第一关:很简单的一个注入 上单引号报错 存在注入,用order  by猜列的个数 union select 出现显示位 查数据库版本,用户和当前数据库名 查表名和列名 最后,激动人心的拿flag

  8. addslashes()

    addslashes() 函数返回在预定义字符之前添加反斜杠的字符串. 作用:防止sql注入

  9. 面试半年,凭借这份JVM面试题,我终于拿到了字节跳动的offer!

    内存区域 虚拟机栈生命周期与线程相同,描述的是Java 方法执行的内存模型,每个方法在执行的时候都会创建一个栈帧,用于存取局部变量表.操作数栈.动态链接.方法出口等信息本地方法栈与虚拟机栈作用相似,只 ...

  10. Vegas视频FX功能详解

    今天呢,小编就带大家走进Vegas(Win系统)视频FX的世界.那么什么是视频FX呢,就是视频制作软件Vegas中自带添加特效的地方,它可以用于添加模糊,黑白,镜像等滤镜效果,各种高大上的视频大片都需 ...