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}$个点与源 ...
随机推荐
- 【BZOJ】4555: [Tjoi2016&Heoi2016]求和 排列组合+多项式求逆 或 斯特林数+NTT
[题意]给定n,求Σi=0~nΣj=1~i s(i,j)*2^j*j!,n<=10^5. [算法]生成函数+排列组合+多项式求逆 [题解]参考: [BZOJ4555][Tjoi2016& ...
- BestCoder Round92
题目链接:传送门 HDU 6015-6018 解题报告:传送门 HDU6015 Skip the Class Accepts: 678 Submissions: 1285 Time Limit: ...
- 原创:HTML 头像截取上传 JS+PHP 整合包~
关于: 关于头像上传这个东西,网上一搜乱七八糟的一堆然而很少很少有自己中意的插件一怒之下就自己写一个... 用法: <!DOCTYPE html> <html lang=" ...
- 天梯赛 L2-009 抢红包
题目链接 没有人没抢过红包吧-- 这里给出N个人之间互相发红包.抢红包的记录,请你统计一下他们抢红包的收获. 输入格式: 输入第一行给出一个正整数N(<= 104),即参与发红包和抢红包的总人数 ...
- redis笔记之两种持久化备份方式(RDB & AOF)
Redis支持的两种持久化备份方式(RDB & AOF) redis支持两种持久化方式,一种是RDB,一种是AOF. RDB是根据指定的规则定时将内存中的数据备份到硬盘上,AOF是在每次执行命 ...
- vue-loader 调用了cssLoaders方法配置了css加载器属性。
module: { loaders: [ // 这里也是相应的配置,test就是匹配文件,loader是加载器, { test: /\.vue$/, loader: 'vue' }, { test: ...
- C#里面中将字符串转为变量名
public partial class Form1 : Form { string str = "spp"; public string spp = "very goo ...
- 生成验证码tp
js里拼接随机数 页面上链接 去掉后缀名
- Pyrhon代码的中文问题
解决代码中出现中文乱码的问题: 使用中文需要在第一行声明编码#encoding=utf-8 或者#coding=utf-8 python只检查#.coding和编码字符串,所以你可能回见到下面的声明方 ...
- 《STL源码剖析》读书笔记
转载:https://www.cnblogs.com/xiaoyi115/p/3721922.html 直接逼入正题. Standard Template Library简称STL.STL可分为容器( ...