Topcoder Srm 726 Div1 Hard

解题思路:

问题可以看做一个二分图,左边一个点向右边一段区间连边,匹配了左边一个点就能获得对应的权值,最大化所得到的权值的和。

然后可以证明一个结论,将点按照权值大小排序后,从大到小加点的充要条件是完美匹配大小 \(+1\) 。考虑如果不是按照这种方式加点的,必然能找到一个没有被匹配的点替换掉一个在匹配中但是权值比它小的点,答案一定会变大。

于是我们可以从大到小枚举点,如果能加进去且完美匹配大小增加就加入这个点,否则就不加。

solutoin1:

一个左侧点能被加进去当且仅当其能找到一条增广路,考虑暴力维护右侧所有在区间内的点出发能否找到增广路,如果可以就等价于当前左边的点是否能和这个右侧点匹配且完美匹配大小增加。

如果这个左侧点被加进去,那么找一个可以合法匹配的右侧点匹配,并减小此条增广路上的流量,考虑任意时刻左边的点数都不会大于右边的点数,所以直接重新BFS一遍求出哪些右侧点可以通过有流量的路径到 \(T\) 即可。

考虑如果有多个右侧的点能和这个左侧的点合法匹配,那么只需要随便选一个即可,因为反向边的存在,选其中任意一个它都可以通过反向边到达其它的右侧点。

这样前面检查的是否有增广路的复杂度是 \(m\) ,后面重新维护的的复杂度是 \(m^2\) ,由于前面的操作最多做 \(n\) 次,后面的操作最多做 \(m\) 次,总复杂度 \(O(nm+m^3)\)。

考虑用一个线段树优化一下建图,那么可以 \(logm\) 判断这一个左侧点是否能被合法匹配,每次重新维护的复杂度变成 \(mlogm\) ,总复杂度优化到 \(O((n+m^2)logm)\)。

Solution2:

扩展一下Hall定理可以得到一个结论,如果要存在完美匹配,当且仅当每一个右侧的区间 \([l ,r]\) 。都要满足

\[r - l + 1 \geq tot
\]

其中 \(tot\) 是左边的点向右侧连边的区间被 \([l,r]\) 完全覆盖的数量。

于是可以维护出每一个区间还能接受的段的数量,每次加入一个点判断所有覆盖它的 \([l,r]\) 是否都还能接受即可。

相当于要维护一个二维平面上从右上角出发的矩形的最值查询和区间减法,用线段树维护一下即可,复杂度也是 \(O((n+m^2)logm)\)。

code (solution1)

/*program by mangoyang*/
#pragma GCC optimize("Ofast", "inline")
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 4000005, T = N - 1;
queue<int> q;
vector<int> d;
int a[N], cap[N], nxt[N], head[N], cnt;
int vis[N], b[N], s[N], size, n, m, ans;
inline void Addedge(int x, int y, int z){
a[++cnt] = y, cap[cnt] = z, nxt[cnt] = head[x], head[x] = cnt;
a[++cnt] = x, cap[cnt] = 0, nxt[cnt] = head[y], head[y] = cnt;
}
namespace Seg{
int ok[N], lc[N], rc[N], root;
inline void build(int &u, int l, int r){
u = n + (++size), ok[u] = 1;
if(l == r)
return (void) (b[u] = l, Addedge(u, T, 1));
int mid = l + r >> 1;
build(lc[u], l, mid), build(rc[u], mid + 1, r);
Addedge(u, lc[u], inf);
Addedge(u, rc[u], inf);
}
inline void addedge(int u, int l, int r, int L, int R, int x){
if(l >= L && r <= R)
return (void) (Addedge(x, u, inf));
int mid = l + r >> 1;
if(L <= mid) addedge(lc[u], l, mid, L, R, x);
if(mid < R) addedge(rc[u], mid + 1, r, L, R, x);
}
inline void rebuild(int u, int l, int r, int a[]){
if(l == r) return (void) (ok[u] = a[l]);
int mid = l + r >> 1;
rebuild(lc[u], l, mid, a);
rebuild(rc[u], mid + 1, r, a); ok[u] = ok[lc[u]] | ok[rc[u]];
}
inline int query(int u, int l, int r, int L, int R){
if(l >= L && r <= R) return ok[u];
int mid = l + r >> 1, res = 0;
if(L <= mid) res |= query(lc[u], l, mid, L, R);
if(mid < R) res |= query(rc[u], mid + 1, r, L, R);
return res;
}
}
inline bool dfs(int u){
if(u == T) return 1; vis[u] = 1;
for(int p = head[u]; p; p = nxt[p])
if(cap[p] > 0 && !vis[a[p]] && dfs(a[p]))
return cap[p]--, cap[p^1]++, 1;
return 0;
}
inline void bfs(){
q.push(T), vis[T] = 1;
for(int i = 0; i < d.size(); i++) vis[d[i]] = 0;
for(int i = 1; i <= size; i++) vis[i+n] = 0;
for(; !q.empty(); q.pop()){
int u = q.front();
for(int p = head[u]; p; p = nxt[p]) if(cap[p^1] > 0)
if(!vis[a[p]]) vis[a[p]] = 1, q.push(a[p]);
}
for(int i = 1; i <= size; i++) if(b[n+i]) s[b[n+i]] = vis[n+i];
Seg::rebuild(Seg::root, 1, m, s);
for(int i = 0; i < d.size(); i++) vis[d[i]] = 0;
for(int i = 1; i <= size; i++) vis[i+n] = 0; vis[T] = 0;
}
struct Node{ int l, r, w; } p[N];
inline bool cmp(Node A, Node B){ return A.w > B.w; }
int main(){
cnt = 1; read(n), read(m);
for(int i = 1; i <= n; i++)
read(p[i].l), read(p[i].r), read(p[i].w);
sort(p + 1, p + n + 1, cmp);
Seg::build(Seg::root, 1, m);
for(int i = 1; i <= n; i++){
if(p[i].l > p[i].r) continue;
if(!Seg::query(Seg::root, 1, m, p[i].l, p[i].r)) continue;
ans += p[i].w, Seg::addedge(Seg::root, 1, m, p[i].l, p[i].r, i);
d.push_back(i), dfs(i), bfs();
}
cout << ans;
}

Topcoder Srm 726 Div1 Hard的更多相关文章

  1. Topcoder SRM 643 Div1 250<peter_pan>

    Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...

  2. topcoder srm 714 div1

    problem1 link 倒着想.每次添加一个右括号再添加一个左括号,直到还原.那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号. problem2 link 令$h(x) ...

  3. topcoder srm 738 div1 FindThePerfectTriangle(枚举)

    Problem Statement      You are given the ints perimeter and area. Your task is to find a triangle wi ...

  4. Topcoder SRM 602 div1题解

    打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...

  5. Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

    Problem Statement      The Happy Letter game is played as follows: At the beginning, several players ...

  6. Topcoder SRM 584 DIV1 600

    思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...

  7. TopCoder SRM 605 DIV1

    604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...

  8. topcoder srm 575 div1

    problem1 link 如果$k$是先手必胜那么$f(k)=1$否则$f(k)=0$ 通过对前面小的数字的计算可以发现:(1)$f(2k+1)=0$,(2)$f(2^{2k+1})=0$,(3)其 ...

  9. topcoder srm 640 div1

    problem1 link 首先使用两个端点颜色不同的边进行连通.答案是$n-1-m$.其中$m$是联通分量的个数. problem2 link 首先构造一个最小割的模型.左边的$n_{1}$个点与源 ...

随机推荐

  1. wampserver 虚拟主机

    转载:http://blog.csdn.net/knight_quan/article/details/51830683 1.背景: 在进行网站开发的时候,通常需要以http://localhost或 ...

  2. C# 加密解密以及sha256不可逆加密案例

    class Program { static void Main(string[] args) { string aa = "身份证"; string bb = "key ...

  3. supervisor 的使用

    1.通过yum安装 supervisor: 2.supervisorctl 查看状态: 3.supervisor.d 下查看配置文件,修改命令和日志目录 4.tail -f /var/log/supe ...

  4. 接口测试(概念、Postman、SoapUI、jmeter)

    一.什么是接口测试 接口测试是测试系统组件间接口的一种测试.接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点.测试的重点是要检查数据的交换,传递和控制管理过程,以及系统间的相互逻辑 ...

  5. Effective C++笔记(三):资源管理

    参考:http://www.cnblogs.com/ronny/p/3745098.html 资源:动态分配的内存.文件描述器.互斥锁.图形界面中的字型与笔刷.数据库连接以及网络sockets等,   ...

  6. webuploader插件使用分析

    大致架构: 前端:html5+ajax 后端:java (struts框架相关) 碰到问题: 后台coder给我提供一个接口./file/uploader.do?upFile=?,让我上传文件对应up ...

  7. 一键去除网页BOM属性【解决乱码,头部空白,&#65279问题】

    几个常出现的问题: 1.网站打开空白 2.页面头部出现多余的空白 3.网站出现乱码,如“锘�” 解决方法可以是: 1.选用专业的编辑器,例如notepad++,sublime,editplus这样不会 ...

  8. 一张图总结html5新特性

  9. TGPPen 宽度的理解

    procedure TForm4.Button1Click(Sender: TObject); var g: TGPGraphics; p: TGPPen; begin g := TGPGraphic ...

  10. 如何去除decimal后面的零?

    如何去除decimal后面的零? 1.260000m.ToString("G29") 不显示科学记数法? decimal.Parse("0.0000001",S ...