bzoj3693: 圆桌会议 二分图 hall定理
目录
题目链接
题解
对与每个人构建二分,问题化为时候有一个匹配取了所有的人
Hall定理——对于任意的二分图G,G的两个部分为X={x1,x2,…,xn}和Y={y1,y2,…,ym},
存在一个匹配M使得|M|=|X|的充要条件为对于X的任意一个子集A,与A相邻的点集记为T(A),一定有|T(A)|≥|A|
拆环为链
对于任意的区间[L,R],长度R-L+1,将所有区间[L,R]内的组插入操作求和为sum,如果sum > R - L + 1,显然不存在满足条件的匹配,否则一定存在解
对于有意义的区间[L,R]一定在给出的操作区间上
sum > R - L + 1 也就是 sum + P - 1 > Q
前面那部分线段树维护
对于每个右端点询问区间,每次把ai的值加到左端点上
对于右端点扫过去就行了
代码
/*
对与每个人构建二分,问题化为时候有一个匹配取了所有的人
> Hall定理——对于任意的二分图G,G的两个部分为X={x1,x2,…,xn}和Y={y1,y2,…,ym},
存在一个匹配M使得|M|=|X|的充要条件为对于X的任意一个子集A,与A相邻的点集记为T(A),一定有|T(A)|≥|A|
拆环为链
对于任意的区间[L,R],长度R-L+1,将所有区间[L,R]内的组插入操作求和为sum,如果sum > R - L + 1,显然不存在满足条件的匹配,否则一定存在解
对于有意义的区间[L,R]一定在给出的操作区间上
sum > R - L + 1 也就是 sum + P - 1 > Q
前面那部分线段树维护
对于每个右端点询问区间,每次把ai的值加到左端点上
对于右端点扫过去就行了
*/
#include<map>
#include<vector>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define pc putchar
#define LL long long
inline int read() {
int x = 0,f = 1;
char c = gc;
while(c < '0' || c > '9')c = gc;
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = gc;
return x * f;
}
void print(int x) {
if(x < 0) {
pc('-');
x = -x;
}
if(x >= 10) print(x / 10);
pc(x % 10 + '0');
}
const int maxn = 1000007;
struct Q {
int l,r,v;
bool operator < (const Q & k)const {
return r < k.r;
}
} q[maxn];
int d[maxn],cnt ,num;
int mx[maxn << 1],tag[maxn << 1];
int n,m;
#define ls x << 1,l,mid
#define rs x << 1 | 1,mid + 1,r
void update(int x) {
mx[x] = std::max(mx[x << 1],mx[x << 1 | 1]);
}
void build(int x,int l,int r) {
mx[x] = tag[x] = 0;
if(l == r) {
mx[x] = d[l] - 1; return;
}
int mid = l + r >> 1;
build(ls);
build(rs);
update(x);
}
inline void pushdown(int x) {
if(!tag[x]) return;
tag[x << 1] += tag[x]; tag[x << 1 | 1] += tag[x];
mx[x << 1] += tag[x]; mx[x << 1 | 1] += tag[x];
tag[x] = 0;
}
void modify(int x,int l,int r,int L,int R,int val) {
if(L <= l && R >= r) {
tag[x] += val,mx[x] += val;
return;
}
pushdown(x);
int mid = l + r >> 1;
if(L <= mid) modify(ls,L,R,val);
if(R > mid) modify(rs,L,R,val);
update(x);
}
int query(int x,int l,int r,int L,int R) {
if(l >= L && R >= r) return mx[x];
pushdown (x);
int mid = l + r >> 1,ans = 0;
if(L <= mid) ans = std::max(query(ls,L,R),ans);
if(R > mid) ans = std::max(query(rs,L,R),ans);
return ans;
}
int main() {
int T = read();
for(int t = 1;t <= T;t += 1) {
cnt = num = 0;
n = read(),m = read();
bool flag = false;
LL sum = 0;
for(int i = 1;i <= n;++ i) {
q[i].l = read(),q[i].r = read(),q[i].v = read();
q[i].l ++;q[i].r ++;sum += q[i].v;
}
if(sum > m) {
puts("No"); continue;
}
cnt = n;
for(int i = 1;i <= n;++ i)
if(q[i].r < q[i].l) q[i].r += m;
else {
q[++cnt] = q[i];
q[cnt].l += m;q[cnt].r += m;
}
n = cnt;
for(int i = 1;i <= n;++ i) d[++ num] = q[i].l,d[++ num] = q[i].r;
std::sort(d + 1,d + num + 1);
std::sort(q + 1,q + n + 1);
build(1,1,n << 1);
for(int i = 1;i <= n;++ i)
q[i].l = std::lower_bound(d + 1,d + num + 1,q[i].l) - d,
q[i].r = std::lower_bound(d + 1,d + num + 1,q[i].r) - d;
for(int i = 1;i <= n;++ i) {
modify(1,1,n << 1,1,q[i].l,q[i].v);
//int k = query(1,1,n << 1,std::max(q[i].r - m + 1,1),q[i].r);
//print(k); pc('\n');
if(query(1,1,n << 1,std::max(q[i].r - m + 1,1),q[i].r) > d[q[i].r]) {
flag = true;
break;
}
}
puts(flag ? "No" : "Yes");
}
return 0;
}
bzoj3693: 圆桌会议 二分图 hall定理的更多相关文章
- 二分图hall定理应用+二分+双指针——cf981F(好题)
/* 二分答案,判mid是否合法 如何判断:如果是在直线上,那么遍历匹配即可 现在在环上,即既可以向前匹配也可以向后匹配,那么将环拆开,扩展成三倍 显然a和b的匹配边是不可能交叉的,因为交叉必定没有不 ...
- BZOJ3693: 圆桌会议(Hall定理 线段树)
题意 题目链接 Sol 好的又是神仙题... 我的思路:对于区间分两种情况讨论,一种是完全包含,另一种是部分包含.第一种情况非常好判断,至于计算对于一个区间[l, r]的$\sum a[i]$就可以了 ...
- Hall定理 二分图完美匹配
充分性证明就先咕了,因为楼主太弱了,有一部分没看懂 霍尔定理内容 二分图G中的两部分顶点组成的集合分别为X, Y(假设有\(\lvert X \rvert \leq \lvert Y \rvert\) ...
- 【CF981F】Round Marriage(二分答案,二分图匹配,Hall定理)
[CF981F]Round Marriage(二分答案,二分图匹配,Hall定理) 题面 CF 洛谷 题解 很明显需要二分. 二分之后考虑如果判定是否存在完备匹配,考虑\(Hall\)定理. 那么如果 ...
- Card Collector AtCoder - 5168(二分图匹配的HALL定理)
题意: 给定一个H行W列的矩阵,在矩阵的格点上放带权值的卡片(一个点上能放多张). 现在从每行每列各拿走一张卡片(没有可以不拿),求可以拿到的最大权值. 卡片数N<=1e5,H,W<=1e ...
- BZOJ.3693.圆桌会议(Hall定理 线段树)
题目链接 先考虑链.题目相当于求是否存在完备匹配.那么由Hall定理,对于任意一个区间[L,R],都要满足[li,ri]完全在[L,R]中的ai之和sum小于等于总位置数,即R-L+1.(其实用不到H ...
- TCO 2015 1A Hard.Revmatching(Hall定理)
\(Description\) 给定一个\(n\)个点的二分图,每条边有边权.求一个边权最小的边集,使得删除该边集后不存在完备匹配. \(n\leq20\). \(Solution\) 设点集为\(S ...
- BZOJ.5404.party(树链剖分 bitset Hall定理)
题目链接 只有指向父节点的单向道路,所以c个人肯定在LCA处汇合.那么就成了有c条到LCA的路径,求最大的x,满足能从c条路径中各选出x个数,且它们不同. 先要维护一条路径的数的种类数,可以树剖+每条 ...
- 【BZOJ2138】stone Hall定理+线段树
[BZOJ2138]stone Description 话说Nan在海边等人,预计还要等上M分钟.为了打发时间,他玩起了石子.Nan搬来了N堆石子,编号为1到N,每堆包含Ai颗石子.每1分钟,Nan会 ...
随机推荐
- java并发编程系列一、多线程
一.什么是线程 一个应用就是一个进程.一个进程由多个线程组成.一个生产车间比作是一个进程.工人比作是线程.当任务比较多的时候,增加工人可以提高效率,同时成本就是支付费用(机器资源,内存)也会增加. p ...
- opencv 图像深度(depth)
原文地址:http://blog.csdn.net/dingfc/article/details/7457984 图像深度是指存储每个像素所用的位数,也用于量度图像的色彩分辨率.图像深度确定彩色图像的 ...
- 生产环境elasticsearch5.0.1和6.3.2集群的部署配置详解
线上环境elasticsearch5.0.1集群的配置部署 es集群的规划: 硬件: 7台8核.64G内存.2T ssd硬盘加1台8核16G的阿里云服务器 其中一台作为kibana+kafka连接查询 ...
- nagios系列(七)nagios通过自定义脚本的方式监控mysql主从同步
nagios监控mysql主从同步 起因:nagios可能监控到mysql服务的运行情况,但确不能监控mysql的主从复制是否正常:有时候,同步已经停止,但管理人员却不知道. 登陆mysql从服务器, ...
- webpack文件笔记
webpack.prod.conf.js里面的ExtractTextPlugin,把css文件提取出来,专门进行打包minify :压缩 依赖的第三方库打包到vendor.js里面 每次项目打包的时候 ...
- java中文GBK和UTF-8编码转换乱码的分析
原文:http://blog.csdn.net/54powerman/article/details/77575656 作者:54powerman 一直以为,java中任意unicode字符串,可以使 ...
- 【linux】ubuntu下crontab无效解决方法
在Debain的docker中启用crontab,踩了一整天的坑,特地记录一下.Debain和ubuntu差不多,故算在ubuntu下面了. 1.第一个坑,安装crontab apt-get inst ...
- confusion_matrix(混淆矩阵)
作者:十岁的小男孩 凡心所向,素履可往 目录 监督学习—混淆矩阵 是什么?有什么用?怎么用? 非监督学习—匹配矩阵 混淆矩阵 矩阵每一列代表预测值,每一行代表的是实际的类别.这个名字来源于它可以非常容 ...
- charAt和String的用法
package charpter2; import java.util.Scanner; public class Test { public static void main(String[] ar ...
- List中存放字符串进行排序
package com.bjpowernode.t03sort; import java.util.ArrayList;import java.util.Collections; /* * List中 ...