BZOJ3693: 圆桌会议(Hall定理 线段树)
题意
Sol
好的又是神仙题。。。
我的思路:对于区间分两种情况讨论,一种是完全包含,另一种是部分包含。
第一种情况非常好判断,至于计算对于一个区间[l, r]的$\sum a[i]$就可以了,但是后两种呢?qwq。想了半天也没想出来。
看了下题解,果然还有更高端的操作!
首先这题可以看是二分图匹配,最暴力的写法是对于每个a[i],直接拆成a[i]个点,然后分别向$[l_i, r_i]$连边,最后看是否能完全匹配。
有一个专门判断这玩意儿的定理:
Hall定理:
二部图G中的两部分顶点组成的集合分别为$X, Y$, $X = \{X1, X2, X3,X4,.........,Xm\},$Y=\{y1, y2, y3, y4 ,.........,yn\},G中有一组无公共点的边,一端恰好为组成X的点的充分必要条件是:
X中的任意k个点至少与Y中的k个点相邻。(1≤k≤m)
对于此题来说,直接应用Hall定理得到的推论为:对于任意的x个人,都至少对应x条边与其相连
然而这样好像还是不好搞,考虑一步步推广
1、对于任意一个询问$[l, r], a_i$,若$a_i$满足要求,那么任意的$x <= a_i$,都满足要求。
这是显然的,因为每个$a_i$连的点都是相同的
2、对于任意的区间$[l, r]$,若他们包含的$a[i]$, $\sum a[i] <= r - l + 1$满足条件,则去掉任意的$a[i]$后,该区间仍然满足条件。
同样显然。
这样我们就把给出的问题转化为:判断对于任意$[l_j, r_i]$,是否满足条件
对所有询问按右端点排序后线段树维护
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<cstring>
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
#define LL long long
using namespace std;
const int MAXN = * 1e6 + , mod = 1e9 + ;
inline LL read() {
char c = getchar(); LL x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
#define ls k << 1
#define rs k << 1 | 1
int T, N, M;
int mx[MAXN], f[MAXN], date[MAXN];
struct Qu {
int l, r, a;
bool operator < (const Qu &rhs) const {
return r == rhs.r ? l < rhs.l : r < rhs.r;
}
}q[MAXN];
void update(int k) {
mx[k] = max(mx[ls], mx[rs]);
}
void add(int k, int val) {
mx[k] += val, f[k] += val;
}
void pushdown(int k) {
if(f[k]) add(ls, f[k]), add(rs, f[k]), f[k] = ;
}
void IntAdd(int k, int ll, int rr, int l, int r, int val) {
if(ll <= l && r <= rr) {add(k, val); return ;}
int mid = l + r >> ;
pushdown(k);
if(ll <= mid) IntAdd(ls, ll, rr, l, mid, val);
if(rr > mid) IntAdd(rs, ll, rr, mid + , r, val);
update(k);
}
int Query(int k, int ll, int rr, int l, int r) {
if(ll <= l && r <= rr) return mx[k];
int mid = l + r >> ;
pushdown(k);
if(ll > mid) return Query(rs, ll, rr, mid + , r);
else if(rr <= mid) return Query(ls, ll, rr, l, mid);
else return max(Query(ls, ll, rr, l, mid), Query(rs, ll, rr, mid + , r));
}
main() {
T = read();
while(T--) {
memset(mx, , sizeof(mx));
memset(f, , sizeof(f));
N = read(); M = read();
int cnt = , tot = ;
LL sum = ;
for(int i = ; i <= N; i++) {
q[++cnt].l = read(), q[cnt].r = read(), q[cnt].a = read();
sum += q[cnt].a;
if(q[cnt].l > q[cnt].r) q[cnt].r += M;
else if(q[cnt].r < M) q[cnt + ] = (Qu) {q[cnt].l + M, q[cnt].r + M, q[cnt].a}, cnt++;
}
if(sum > M) {puts("No"); continue;}
for(int i = ; i <= cnt; i++) q[i].l++, q[i].r++, date[++tot] = q[i].l, date[++tot] = q[i].r;
for(int i = ; i <= * N; i++) date[++tot] = i; sort(q + , q + cnt + );
sort(date + , date + tot + );
tot = unique(date + , date + tot + ) - date - ; int cur = , flag = ;
for(int i = ; i <= cnt; i++) {
int l = q[i].l, r = q[i].r;
l = lower_bound(date + , date + tot + , l) - date;
r = lower_bound(date + , date + tot + , r) - date;
while(cur < r) cur++, IntAdd(, cur, cur, , tot, date[cur] - );
IntAdd(, , l, , tot, q[i].a);
int val = Query(, , r, , tot);
if(val > date[r]) {puts("No"); flag = ; break;}
}
if(!flag) puts("Yes"); }
return ;
}
BZOJ3693: 圆桌会议(Hall定理 线段树)的更多相关文章
- BZOJ.3693.圆桌会议(Hall定理 线段树)
题目链接 先考虑链.题目相当于求是否存在完备匹配.那么由Hall定理,对于任意一个区间[L,R],都要满足[li,ri]完全在[L,R]中的ai之和sum小于等于总位置数,即R-L+1.(其实用不到H ...
- [BZOJ3693]圆桌会议[霍尔定理+线段树]
题意 题目链接 分析 又是一个二分图匹配的问题,考虑霍尔定理. 根据套路我们知道只需要检查 "区间的并是一段连续的区间" 这些子集. 首先将环倍长.考虑枚举答案的区间并的右端点 \ ...
- LOJ.6062.[2017山东一轮集训]Pair(Hall定理 线段树)
题目链接 首先Bi之间的大小关系没用,先对它排序,假设从小到大排 那么每个Ai所能匹配的Bi就是一个B[]的后缀 把一个B[]后缀的匹配看做一条边的覆盖,设Xi为Bi被覆盖的次数 容易想到 对于每个i ...
- loj#6062. 「2017 山东一轮集训 Day2」Pair hall定理+线段树
题意:给出一个长度为 n的数列 a和一个长度为 m 的数列 b,求 a有多少个长度为 m的连续子数列能与 b匹配.两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对当 ...
- 模拟赛 怨灵退治 题解(Hall定理+线段树)
题意: 有 n 群怨灵排成一排,燐每秒钟会选择一段区间,消灭至多 k 只怨灵. 如果怨灵数量不足 k,则会消灭尽量多的怨灵. 燐作为一只有特点的猫,它选择的区间是不会相互包含的.它想要知道它每秒最多能 ...
- Codeforces 338E - Optimize!(Hall 定理+线段树)
题面传送门 首先 \(b_i\) 的顺序肯定不会影响匹配,故我们可以直接将 \(b\) 数组从小到大排个序. 我们考虑分析一下什么样的长度为 \(m\) 的数组 \(a_1,a_2,\dots,a_m ...
- 【BZOJ2138】stone Hall定理+线段树
[BZOJ2138]stone Description 话说Nan在海边等人,预计还要等上M分钟.为了打发时间,他玩起了石子.Nan搬来了N堆石子,编号为1到N,每堆包含Ai颗石子.每1分钟,Nan会 ...
- BZOJ1135 LYZ(POI2009) Hall定理+线段树
做这个题之前首先要了解判定二分图有没有完备匹配的Hall定理: 那么根据Hell定理,如果任何一个X子集都能连大于等于|S|的Y子集就可以获得完备匹配,那么就是: 题目变成只要不满足上面这个条件就能得 ...
- ARC076 F Exhausted? Hall定理 + 线段树扫描线
---题面--- 题目大意: 有n个人,m个座位,每个人可以匹配的座位是[1, li] || [ri, m],可能有人不需要匹配座位(默认满足),问最少有多少人不能被满足. 题解: 首先可以看出这是一 ...
随机推荐
- display与position之间的关系
以防自己忘记写的 网上找的 positon 与 display 的相互关系 元素分为内联元素和区块元素两类(当然也有其它的),在内联元素中有个非常重要的常识,即内两元素是不可以设置区块元素所具有的样式 ...
- 第 2 章 Python 语言入⻔
目录 2.1低而长的学习曲线 2.2Python的优势 2.3在你的计算机中安装Python 2.4如何运行Python程序 2.5文本编辑器 2.6寻求帮助 Python语言是一种流行的编程语言,在 ...
- 8、scala函数式编程
一.函数式编程1 1.介绍 Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象, 而且只有方法的概念 ...
- Linux进程KILL不掉的原因
做过Linux开发的人通常遇到过一个进程不能kill掉的情况,即使使用的是kill -9方式,而一般的教课书都只说kill -9能杀死任何进程,遇到这种情况时就会感觉到很矛盾,其它这也是正常的,通常有 ...
- 【转】JAVA输出内容打印到TXT以及不同系统中如何换行
JAVA输出内容打印到TXT以及不同系统中如何换行 http://xiyang.09.blog.163.com/blog/static/59827615201172552755293/ 2011-08 ...
- Algorithms - Fibonacci Number
斐波那契数列(Fibonacci Number)从数学的角度是以递归的方法定义的: \(F_0 = 0\) \(F_1 = 1\) \(F_n = F_{n-1} + F_{n-2}\) (\(n \ ...
- vue+element-ui 实现分页
<el-table ref="multipleTable" :data="tableData.slice((currentPage-1)*pagesize,curr ...
- 基本图形的绘制(基于skimage)
图形包括线条.圆形.椭圆形.多边形等.在skimage包中,绘制图形用的是draw模块,不要和绘制图像搞混了. 一 线条 函数调用格式: skimage.draw.line(r1,c1,r2 ...
- SQL Server 2012安装——.net framework 3.5离线安装
前言 电脑用着一直很不舒服,所以就决定对电脑重新配置一番,在装数据库这里,可谓是屡装屡败.自己感觉太麻烦了,于是每次数据库装失败后,就重装系统,然后配置上网文档,这样一来,弄得自己挺恶心,这次很明显成 ...
- 如何阻止<a>标签的页面跳转
当页面中a标签不需要执行任何页面跳转行为时: 1.标签属性href,使其指向空或不返回任何内容 <a href="javascript:void(0);" >页面不跳转 ...