【LOJ6062】「2017 山东一轮集训 Day2」Pair(线段树套路题)
大致题意: 给出一个长度为\(n\)的数列\(a\)和一个长度为\(m\)的数列\(b\),求\(a\)有多少个长度为\(m\)的子串与\(b\)匹配。数列匹配指存在一种方案使两个数列中的数两两配对,数配对指它们的和不小于\(h\)。
预处理
显然,要判断两个数列是否匹配,肯定是将一个数列从小到大排序,另一个数列从大到小排序,然后逐一判断相应位置上的两个数是否配对。
我们可以将其转化,把\(b_i\)变成\(h-b_i\),然后将\(a\)的某个子串和\(b\)都从大到小排序,再比较相应位置上\(a_i\)是否大于等于\(b_i\),即可判断是否匹配。
线段树优化
然后就可以发现这是一道线段树套路题。
考虑要对应位置\(a_i\)大于等于\(b_i\),且\(b_1\le b_2\le b_3\le...\le b_n\),则对于\(b_i\),应该有\(\ge i\)个数大于等于它。
所以,我们可以将\(a,b\)离散化,对于每个\(b_i\),在线段树第\(b_i\)个位置上减\(i\),对于每个\(a_i\),在线段树第\([1,a_i]\)这个区间上加\(1\)。
因此,判断线段树中是否所有元素大于等于\(0\)即可判断两个序列是否匹配(这只须记录一个最小值就能判)。
要注意的是,对于重复的\(b_i\),我们只选择最大的\(i\)减去,而不是叠加。
既然这样,我们枚举\(a\)中子串右端点\(i\),每次删去第\(i-m\)个数,然后加上第\(i\)个数,若当前情况合法则将\(ans\)加\(1\)即可。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 150000
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
int n,m,h,dc,a[N+5],b[N+5],dv[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
class SegmentTree//线段树
{
private:
#define L l,mid,rt<<1,tl,tr
#define R mid+1,r,rt<<1|1,tl,tr
#define PU(x) (O[x]=O[x<<1]+O[x<<1|1])
#define PD(x) (O[x].F&&(O[x<<1]+=O[x].F,O[x<<1|1]+=O[x].F,O[x].F=0))
struct node//存储节点信息
{
int Mn,F;I node(CI mn=0,CI f=0):Mn(mn),F(f){}
I node operator + (Con node& o) Con {return node(min(Mn,o.Mn));}
I void operator += (CI x) {Mn+=x,F+=x;}
}O[N<<2];
I void upt(CI l,CI r,CI rt,CI tl,CI tr,CI v)//区间修改
{
if(tl<=l&&r<=tr) return O[rt]+=v;PD(rt);RI mid=l+r>>1;
tl<=mid&&(upt(L,v),0),tr>mid&&(upt(R,v),0),PU(rt);
}
public:
I void Update(CI l,CI r,CI v) {upt(1,n,1,l,r,v);}
I bool Check() {return O[1].Mn>=0;}//判断最小值是否大于等于0
}S;
I int GV(CI x)//求出离散化后的值
{
RI l=1,r=dc,mid;W(l<=r) dv[mid=l+r>>1]<x?l=mid+1:r=mid-1;
return l;
}
int main()
{
RI i,ans=0;for(F.read(n,m,h),i=1;i<=m;++i) F.read(b[i]);//读入
for(sort(b+1,b+m+1),i=1;i<=n;++i) F.read(a[i]),dv[i]=a[i];
sort(dv+1,dv+n+1),dc=unique(dv+1,dv+n+1)-dv-1;for(i=1;i<=n;++i) a[i]=GV(a[i]);//离散化
for(i=1;i<=m;++i) b[i]=GV(h-b[i]),b[i]<h&&(S.Update(b[i],b[i],b[i]^b[i-1]?-i:-1),0);//离散化,并在线段树上初始化,注意判重
for(i=1;i<=m;++i) S.Update(1,a[i],1);ans+=S.Check();//将前m个数加入,更新ans
for(i=m+1;i<=n;++i) S.Update(1,a[i-m],-1),S.Update(1,a[i],1),ans+=S.Check();//每次删除第i-m个数,加上第i个数,然后更新ans
return printf("%d",ans),0;//输出答案
}
【LOJ6062】「2017 山东一轮集训 Day2」Pair(线段树套路题)的更多相关文章
- LOJ6062「2017 山东一轮集训 Day2」Pair(Hall定理,线段树)
题面 给出一个长度为 n n n 的数列 { a i } \{a_i\} {ai} 和一个长度为 m m m 的数列 { b i } \{b_i\} {bi},求 { a i } \{a_i\} ...
- LOJ #6062. 「2017 山东一轮集训 Day2」Pair
这是Lowest JN dalao昨天上课讲的一道神题其实是水题啦 题意很简单,我们也很容易建模转化出一个奇怪的东西 首先我们对b进行sort,然后我们就可以通过二分来判断出这个数可以和哪些数配对 然 ...
- loj#6062. 「2017 山东一轮集训 Day2」Pair hall定理+线段树
题意:给出一个长度为 n的数列 a和一个长度为 m 的数列 b,求 a有多少个长度为 m的连续子数列能与 b匹配.两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对当 ...
- ACM-ICPC 2017 西安赛区现场赛 K. LOVER II && LibreOJ#6062. 「2017 山东一轮集训 Day2」Pair(线段树)
题目链接:西安:https://nanti.jisuanke.com/t/20759 (计蒜客的数据应该有误,题目和 LOJ 的大同小异,题解以 LOJ 为准) LOJ:https://l ...
- Loj #6069. 「2017 山东一轮集训 Day4」塔
Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...
- Loj #6073.「2017 山东一轮集训 Day5」距离
Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...
- Loj 6068. 「2017 山东一轮集训 Day4」棋盘
Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...
- 「2017 山东一轮集训 Day5」苹果树
「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...
- 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)
[LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...
随机推荐
- spring初始化bean的目的
初始化bean就是为了将所有需要的bean全部装载到容器里面,等我们需要用到哪个bean就将哪个bean从容器里面拿出来
- [转]NetCat简介
NetCat是一个非常简单的Unix工具,可以读.写TCP或UDP网络连接(network connection).它被设计成一个可靠的后端(back-end) 工具,能被其它的程序或脚本直接地或容易 ...
- Vim as a Python IDE
参考视频:http://v.youku.com/v_show/id_XNDY4NTM4NzY0.html 好的,在我们默认的centos6的操作系统中使用的python2,我们一般会再去安装一个pyt ...
- 第十六章:自定义push notification sound
前面一节已经讲过如何在ionic中集成jpush,这样我们的hybrid app在部署到ios或者android上面的时候,就可以接收通知了.如果不满足系统自带的声音,可以通过一些方式来播放自定义的通 ...
- how to use Sqoop to import/ export data
Sqoop is a tool designed for efficiently transferring data between RDBMS and HDFS, we can import dat ...
- Ace教你一步一步做Android新闻客户端(一)
复制粘贴了那么多博文很不好意思没点自己原创的也说不出去,现在写一篇一步一步教你做安卓新闻客户端,借此机会也是让自己把相关的技术再复习一遍,大神莫笑,专门做给新手看. 手里存了两篇,一个包括软件视图 和 ...
- Unity3d Attribute 总结
举两个例子,在变量上使用[SerializeFiled]属性,可以强制让变量进行序列化,可以在Unity的Editor上进行赋值. 在Class上使用[RequireComponent]属性,就会在C ...
- 简单springboot及springboot cloud环境搭建
springboot使用特定的方式,简化了spring的各种xml配置文件,并通过maven或者gradle,完成所需依赖,使用springboot maven插件,可直接输出可运行的jar包,省去了 ...
- Path类 操作文件类
// Path类 IO命名空间 静态类 不能创建对象类名. string str =@"E:\C#程序设计基础入门教程\(第十一天)\122\22\nee.txt"; ////in ...
- HTML5 总结 (1)
HTML5新表单 1.Input 新类型:email url tel number range date color date week month....... <html> < ...