目录

题目链接

bzoj3693: 圆桌会议

题解

对与每个人构建二分,问题化为时候有一个匹配取了所有的人

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定理的更多相关文章

  1. 二分图hall定理应用+二分+双指针——cf981F(好题)

    /* 二分答案,判mid是否合法 如何判断:如果是在直线上,那么遍历匹配即可 现在在环上,即既可以向前匹配也可以向后匹配,那么将环拆开,扩展成三倍 显然a和b的匹配边是不可能交叉的,因为交叉必定没有不 ...

  2. BZOJ3693: 圆桌会议(Hall定理 线段树)

    题意 题目链接 Sol 好的又是神仙题... 我的思路:对于区间分两种情况讨论,一种是完全包含,另一种是部分包含.第一种情况非常好判断,至于计算对于一个区间[l, r]的$\sum a[i]$就可以了 ...

  3. Hall定理 二分图完美匹配

    充分性证明就先咕了,因为楼主太弱了,有一部分没看懂 霍尔定理内容 二分图G中的两部分顶点组成的集合分别为X, Y(假设有\(\lvert X \rvert \leq \lvert Y \rvert\) ...

  4. 【CF981F】Round Marriage(二分答案,二分图匹配,Hall定理)

    [CF981F]Round Marriage(二分答案,二分图匹配,Hall定理) 题面 CF 洛谷 题解 很明显需要二分. 二分之后考虑如果判定是否存在完备匹配,考虑\(Hall\)定理. 那么如果 ...

  5. Card Collector AtCoder - 5168(二分图匹配的HALL定理)

    题意: 给定一个H行W列的矩阵,在矩阵的格点上放带权值的卡片(一个点上能放多张). 现在从每行每列各拿走一张卡片(没有可以不拿),求可以拿到的最大权值. 卡片数N<=1e5,H,W<=1e ...

  6. BZOJ.3693.圆桌会议(Hall定理 线段树)

    题目链接 先考虑链.题目相当于求是否存在完备匹配.那么由Hall定理,对于任意一个区间[L,R],都要满足[li,ri]完全在[L,R]中的ai之和sum小于等于总位置数,即R-L+1.(其实用不到H ...

  7. TCO 2015 1A Hard.Revmatching(Hall定理)

    \(Description\) 给定一个\(n\)个点的二分图,每条边有边权.求一个边权最小的边集,使得删除该边集后不存在完备匹配. \(n\leq20\). \(Solution\) 设点集为\(S ...

  8. BZOJ.5404.party(树链剖分 bitset Hall定理)

    题目链接 只有指向父节点的单向道路,所以c个人肯定在LCA处汇合.那么就成了有c条到LCA的路径,求最大的x,满足能从c条路径中各选出x个数,且它们不同. 先要维护一条路径的数的种类数,可以树剖+每条 ...

  9. 【BZOJ2138】stone Hall定理+线段树

    [BZOJ2138]stone Description 话说Nan在海边等人,预计还要等上M分钟.为了打发时间,他玩起了石子.Nan搬来了N堆石子,编号为1到N,每堆包含Ai颗石子.每1分钟,Nan会 ...

随机推荐

  1. Linux时间日期类指令

    ⒈date [Options] 显示/设置当前日期 基本语法: date 显示当前时间 date +"%Y" 显示当前年份 date +"%m" 显示当前月份 ...

  2. 使用SpringSecurity保护方法应用

    (1)pom添加依赖 <dependency> <groupId>org.springframework.security</groupId> <artifa ...

  3. java使用正则表达式的方法从json串儿,取想要的value值

    例子1: 现有json: ({"code":"200","json":["111"],"message&quo ...

  4. PYTHON-模块 sys os random shutil

    import sys # 环境变量# print(sys.path)# # 查看已经加载的模块# print(sys.modules)# # 获取终端调用时的参数# print(sys.argv)# ...

  5. C#面向对象(继承)

  6. v-bind绑定属性样式——class的三种绑定方式

    1.布尔值的绑定方式 <div id="demo"> <span v-bind:class="{‘class-a‘:isA ,‘class-b‘:isB ...

  7. python接口自动化测试二十二:文件下载

    文件下载类型: Content-Type: octets/stream   一般为文件类型:

  8. linux下安装ruby环境

    安装步骤: ruby的shell叫irb,我们可以输入irb -v查看下irb的版本号 1.安装ruby解释器shell: yum install ruby-irb -y Installed: rub ...

  9. C#中IEnumerable、ICollection、IList、IQueryable 、IQueryable 、List之间的区别

    一:一个简单的例子 int[] myArray = { 1, 32, 43, 343 }; IEnumerator myie = myArray.GetEnumerator(); myie.Reset ...

  10. S2750&S5700&S6700 V200R003(C00&C02&C10) MIB参考

    https://support.huawei.com/enterprise/docinforeader.action?contentId=DOC1000027337&idPath=791971 ...