Topcoder Srm 726 Div1 Hard
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]\) 。都要满足
\]
其中 \(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的更多相关文章
- Topcoder SRM 643 Div1 250<peter_pan>
Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...
- topcoder srm 714 div1
problem1 link 倒着想.每次添加一个右括号再添加一个左括号,直到还原.那么每次的右括号的选择范围为当前左括号后面的右括号减去后面已经使用的右括号. problem2 link 令$h(x) ...
- topcoder srm 738 div1 FindThePerfectTriangle(枚举)
Problem Statement You are given the ints perimeter and area. Your task is to find a triangle wi ...
- Topcoder SRM 602 div1题解
打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...
- Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串
Problem Statement The Happy Letter game is played as follows: At the beginning, several players ...
- Topcoder SRM 584 DIV1 600
思路太繁琐了 ,实在不想解释了 代码: #include<iostream> #include<cstdio> #include<string> #include& ...
- TopCoder SRM 605 DIV1
604的题解还没有写出来呢.先上605的. 代码去practice房间找. 说思路. A: 贪心,对于每个类型的正值求和,如果没有正值就取最大值,按着求出的值排序,枚举选多少个类型. B: 很明显是d ...
- 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)其 ...
- topcoder srm 640 div1
problem1 link 首先使用两个端点颜色不同的边进行连通.答案是$n-1-m$.其中$m$是联通分量的个数. problem2 link 首先构造一个最小割的模型.左边的$n_{1}$个点与源 ...
随机推荐
- 数据库-Core Data
技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http://weibo.com/luohanchenyilong 数据库-Core Data 技术博客htt ...
- Let's Encrypt 免费通配 https 签名证书 安装方法2 ,安卓签名无法认证!
Let's Encrypt 免费通配 https 签名证书 安装方法 按照上文 配置完毕后你会发现 在pc浏览器中正常访问,在手机浏览器中无法认证 你只需要安装一个或多个中级证书 1.查看Nginx ...
- 【leetcode 简单】第一题 两数之和
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...
- Linux下文件目录权限和对应命令的总结
Linux下的权限有rwx三种,分别对应读,写,执行三种,在对文件和目录时,分别是下列含义: 对应权限的命令为: 文件: r-- cat, more, head, tail w-- echo, vi ...
- C#调用mciSendString播放音频文件
mciSendString函数是一个WinAPI,主要用来向MCI(Media Control Interface)设备发送字符串命令. 一.函数的声明如下: private static exter ...
- 工作当中遇到的ssh错误
[root@1bcc1d3f9666 externalscripts]# /usr/sbin/sshd Could not load host key: /etc/ssh/ssh_host_rsa_k ...
- word2vec原理
最原始的是NNLM,然后对其改进,有了后面的层次softmax和skip gram 层次softmax:去掉了隐藏层,后面加了huffuman树,concat的映射层也变成了sum skip gram ...
- 安全控制 iptables
转自:http://www.opsers.org/linux-home/videos/chapter-netfilter-iptables-raiders.html 内容简介防火墙的概述iptable ...
- Django之Cookie、Session和自定义分页
cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...
- 洛谷P1339 [USACO09OCT]热浪Heat Wave 题解
题目传送门 这道题实际非常简单好奇是怎么变黄的... 其实也就是一个SPFA,本人非常懒,不想打邻接表,直接用矩阵就好啦... #include<bits/stdc++.h> using ...