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. idea自动识别get set方法

  2. json格式的一些常用操作方法

    package com.liveyc.restfull.until; import java.util.HashMap; import java.util.Iterator; import java. ...

  3. Go Web 编程 第一章 Web相关概念

    第一章 Go与Web应用 Go学习群:415660935 1.1 Web应用 在计算机的世界里,应用(application)是一个与用户进行交互,并完成用户特定任务的软件程序.而Web应用则是部署在 ...

  4. atoll()函数使用注意事项及分析

    atoll是c99标准加入的函数,在编译的时候可能要打开C99标准的编译选项 -std=c99. 另外,必须包含stdlib.h头文件,否则会出错. ☞ C程序代码如下所示: #include < ...

  5. iTextSharp操作pdf之pdfCreater

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. 简单实现JS上传图片预览功能

    HTML代码 <div class="upload"> <input type="button" class="btn" ...

  7. Linux删除除了今天以外的文件

    [背景] 开发到日志记录功能时,每天都会产生当天的一个日志,久而久之就会产生累积,想要查看的时候,tab键无法自动补全,还要自己额外输入. 比较麻烦. [命令] 经过查找和实验,找到了以下的方法: 1 ...

  8. leetcode 之Remove Duplicates from Sorted Array(2)

    描述    Follow up for ”Remove Duplicates”: What if duplicates are allowed at most twice?    For exampl ...

  9. 翻译:MLAPP(2.1节 概率概述)

    笔者:尝试翻译MLAPP(Machine Learning: a Probabilistic Perspective)一书,供机器学习的学者参考,如有错误理解之处请指出,不胜感激!(如需转载,请联系本 ...

  10. 回文词(UVa401)

    详细题目描述见:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_prob ...