BZOJ.3693.圆桌会议(Hall定理 线段树)
先考虑链。题目相当于求是否存在完备匹配。那么由Hall定理,对于任意一个区间[L,R],都要满足[li,ri]完全在[L,R]中的ai之和sum小于等于总位置数,即R-L+1。(其实用不到Hall定理,显然)
为什么不是子集呢,因为区间并和子集等价,所有区间并都是要验证的。
而且可以发现,只有当R为某个r[i],L为某个l[j]时,[L,R]才有必要验证。
所以我们将区间按r[]排序,枚举每个r[i]作为R。限制条件为\(sum<=R-L+1\)即\(sum+L-1<=R\),对于前面所有位置,即\(L∈[1,R]\),我们可以直接用线段树维护每个位置的sum+L-1,查询最大值就可以了。
每次枚举到i,会使\(L∈[1,l[i]]\)时+ai,这个区间加就行了。
至于环,拆环为链就可以了。
但是有个问题,比如m=5,([1,3],2),([3,2],3),会分成区间[1,3],[3,7],[6,8],[3,2]实际是包含[1,3]的,但是[1,3]被分成了[3,3]和[6,7],它的a就不会就加上了。
因为r=l-1时,长为m,会把另一个[l,r]与复制出来的[l+m,r+m]分割开,导致都不包含在[r,l-1]内。
因为这些区间长度都为m,所以只需要先判一下整个区间即可。
r[]不需要离散化,否则注意是与ref[r]比较。。
不难 又浪费很长时间。。
//10496kb 888ms(Rank1!)
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=2e5+5;
int n,m,ref[N];
char IN[MAXIN],*SS=IN,*TT=IN;
struct Opt
{
int l,r,a;
Opt() {}
Opt(int l,int r,int a):l(l),r(r),a(a) {}
bool operator <(const Opt &x)const{
return r<x.r;
}
}q[N];
struct Segment_Tree
{
#define lson rt<<1
#define rson rt<<1|1
#define ToL l,m,rt<<1
#define ToR m+1,r,rt<<1|1
int mx[N<<2],tag[N<<2];
#define Update(rt) mx[rt]=std::max(mx[lson],mx[rson])
// #define Add(rt,v) mx[rt]+=v, tag[rt]+=v
// #define PushDown(rt) Add(lson,tag[rt]), Add(rson,tag[rt]), tag[rt]=0
inline void Add(int rt,int v){
mx[rt]+=v, tag[rt]+=v;
}
void PushDown(int rt){
Add(lson,tag[rt]), Add(rson,tag[rt]), tag[rt]=0;
}
void Build(int l,int r,int rt)
{
tag[rt]=0;
if(l==r) mx[rt]=ref[l]-1;//ref!
else Build(l,l+r>>1,lson), Build((l+r>>1)+1,r,rson), Update(rt);
}
void Modify(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R) {Add(rt,v); return;}
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
if(L<=m) Modify(ToL,L,R,v);
if(m<R) Modify(ToR,L,R,v);
Update(rt);
}
int Query(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) return mx[rt];
if(tag[rt]) PushDown(rt);
int m=l+r>>1;
if(L<=m)
if(m<R) return std::max(Query(ToL,L,R),Query(ToR,L,R));
else return Query(ToL,L,R);
return Query(ToR,L,R);
}
}T;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline int Find(int x,int r)
{
int l=1,mid;
while(l<r)
if(ref[mid=l+r>>1]<x) l=mid+1;
else r=mid;
return l;
}
int main()
{
int Case=read();
while(Case--)
{
n=read(),m=read(); int Q=0,t=0; long long sum=0;
for(int i=1,l,r,a; i<=n; ++i)
{
ref[++t]=l=read(),r=read(),sum+=(a=read());
if(l<=r) q[++Q]=Opt(l,r,a), q[++Q]=Opt(l+m,r+m,a), ref[++t]=l+m/*!*/;
else q[++Q]=Opt(l,r+m,a);
}
if(sum>m) {puts("No"); continue;}
std::sort(q+1,q+1+Q);
std::sort(ref+1,ref+1+t); int cnt=1;
for(int i=2; i<=t; ++i) if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
for(int i=1; i<=Q; ++i) q[i].l=Find(q[i].l,cnt);//, q[i].r=Find(q[i].r,cnt);
n=cnt, T.Build(1,n,1);
bool f=1;
for(int i=1; i<=Q; ++i)
{
T.Modify(1,n,1,1,q[i].l,q[i].a);
if(T.Query(1,n,1,1,q[i].l/*l对?用r还得离散化...*/)>q[i].r) {f=0; break;}//ref[r]
}
puts(f?"Yes":"No");
}
return 0;
}
BZOJ.3693.圆桌会议(Hall定理 线段树)的更多相关文章
- BZOJ3693: 圆桌会议(Hall定理 线段树)
题意 题目链接 Sol 好的又是神仙题... 我的思路:对于区间分两种情况讨论,一种是完全包含,另一种是部分包含.第一种情况非常好判断,至于计算对于一个区间[l, r]的$\sum a[i]$就可以了 ...
- 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 ...
- [BZOJ3693]圆桌会议[霍尔定理+线段树]
题意 题目链接 分析 又是一个二分图匹配的问题,考虑霍尔定理. 根据套路我们知道只需要检查 "区间的并是一段连续的区间" 这些子集. 首先将环倍长.考虑枚举答案的区间并的右端点 \ ...
- 【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],可能有人不需要匹配座位(默认满足),问最少有多少人不能被满足. 题解: 首先可以看出这是一 ...
随机推荐
- JS window对象的top、parent、opener含义介绍
1.top该变更永远指分割窗口最高层次的浏览器窗口.如果计划从分割窗口的最高层次开始执行命令,就可以用top变量. 2.openeropener用于在window.open的页面引用执行该window ...
- Linux系统无线网卡的安装【转】
转自:http://www.linuxidc.com/Linux/2013-03/81473.htm 现在的很多的可移动无线网卡都是usb接口的,把这种网卡应用到windows操作系统上是很容易就能起 ...
- 字符驱动之二操作方法(struct file_operations)【转】
转自:http://blog.chinaunix.net/uid-26837113-id-3157515.html 从上一篇我们看到了字符驱动的三个重要结构,那我现在跟大家详细的说说 struct f ...
- Bootstrap3.0学习第四轮(排版)
详情请查看http://aehyok.com/Blog/Detail/10.html 个人网站地址:aehyok.com QQ 技术群号:206058845,验证码为:aehyok 本文文章链接:ht ...
- 重新学习angularjs--第一篇(入门)
几乎是一年之前,泛泛接触了angularjs,也做了一些项目,但是时至今日,几乎已经忘记了ng的使用,由于业务需要,近日要攻克这座难关,重新学习.会把学习的一些东西拿出来,记录之. angularjs ...
- centos7使用haproxy1.7.5实现反向代理负载均衡实战
使用haproxy实现反向代理负载均衡实战环境准备:两台虚拟机 # yum install -y gcc glibc gcc-c++ make screen tree lrzsz node1源码编译安 ...
- 解决LoggerFactory is not a Logback LoggerContext but Logback is on the classpath
因为引用了log4j2同时还引用了logback
- 调试Windows Service
调试Windows Service 使用一般的调试方法调试不了Windows Servers,所以参考了一些调试方法 我服务源码中使用了Timer,注意不能使用工具箱内的Timer,用System.T ...
- Python3-RabbitMQ 3.7.2学习——环境搭建(一)
学习消息队列,就要把环境先装好,本人使用的是python3.5.2和RabbitMQ 3.7.2,在装RabbitMQ之前,先要装Erlang,一定要. 1.环境:win10系统 python3 ...
- Tomcat开启JMX监控 visualvm
Tomcat开启JMX监控 https://blog.csdn.net/dongdong2980/article/details/78476393