• LOJ #6062. 「2017 山东一轮集训 Day2」Pair


    这是Lowest JN dalao昨天上课讲的一道其实是水题啦

    题意很简单,我们也很容易建模转化出一个奇怪的东西

    首先我们对b进行sort,然后我们就可以通过二分来判断出这个数可以和哪些数配对

    然后我们稍微想一下就可以知道:每一段区间都是b数组后缀的形式

    证明很简单,如果假设当前的数与第(i)位上的(b_i)不匹配,那么对于比(b_i)更小的(b_{i-1})肯定是无法匹配的

    然后我们可以转化为一个类似于二分图的完美匹配的问题,只不过其中匹配的数如上面所言是后缀的形式

    然后我们可以套一个叫霍尔定理的东西,证明自看

    然后我们发现对于所有的(b_i(1le ile m)),都需要有至少i根线段包含了它

    更直接的,我们令一个统计数组(c),开始时(c_i)都等于(-i),这样每次只需要给一个后缀加1即可

    然后查询是否可以实现只需要看一下最小值是否>=0即可

    然后直接做是肯定T的,然后我们发现我们需要完成的任务:

    1. 区间加
    2. 区间减(在抵消之前的操作是会用到)
    3. 区间最值查询

    这不就是线段树随便维护一下的东西吗。

    CODE

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=150005;
    int a[N],b[N],c[N],r[N],n,m,ans,h;
    struct segtree
    {
    	int s,add;
    }tree[N<<2];
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc();
    	while (ch<'0'||ch>'9') ch=tc();
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline int find(int x)
    {
    	int l=1,r=m,res=m+1;
    	while (l<=r)
    	{
    		int mid=l+r>>1;
    		if (b[mid]>=x) res=mid,r=mid-1; else l=mid+1;
    	}
    	return res;
    }
    inline int min(int a,int b)
    {
    	return a<b?a:b;
    }
    inline void up(int rt)
    {
    	tree[rt].s=min(tree[rt<<1].s,tree[rt<<1|1].s);
    }
    inline void down(int rt)
    {
    	if (tree[rt].add)
    	{
    		tree[rt<<1].add+=tree[rt].add; tree[rt<<1|1].add+=tree[rt].add;
    		tree[rt<<1].s+=tree[rt].add; tree[rt<<1|1].s+=tree[rt].add;
    		tree[rt].add=0;
    	}
    }
    inline void build(int rt,int l,int r)
    {
    	if (l==r)
    	{
    		tree[rt].s=c[l];
    		return;
    	}
    	int mid=l+r>>1;
    	build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);
    	up(rt);
    }
    inline void modify(int rt,int l,int r,int beg,int end,int k)
    {
    	if (l>=beg&&r<=end)
    	{
    		tree[rt].add+=k; tree[rt].s+=k;
    		return;
    	}
    	int mid=l+r>>1;
    	down(rt);
    	if (beg<=mid) modify(rt<<1,l,mid,beg,end,k);
    	if (end>mid) modify(rt<<1|1,mid+1,r,beg,end,k);
    	up(rt);
    }
    inline int query(int rt,int l,int r,int beg,int end)
    {
    	if (l>=beg&&r<=end) return tree[rt].s;
    	int mid=l+r>>1,res=1e9;
    	down(rt);
    	if (beg<=mid) res=min(res,query(rt<<1,l,mid,beg,end));
    	if (end>mid) res=min(res,query(rt<<1|1,mid+1,r,beg,end));
    	up(rt); return res;
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	register int i; read(n); read(m); read(h);
    	for (i=1;i<=m;++i)
    	read(b[i]),c[i]=-i; sort(b+1,b+m+1);
    	for (i=1;i<=n;++i)
    	read(a[i]);
    	build(1,1,m);
    	for (i=1;i<=m;++i)
    	{
    		r[i]=find(h-a[i]);
    		if (r[i]<=m) modify(1,1,m,r[i],m,1);
    	}
    	if (query(1,1,m,1,m)>=0) ++ans;
    	for (i=m+1;i<=n;++i)
    	{
    		r[i]=find(h-a[i]);
    		if (r[i-m]<=m) modify(1,1,m,r[i-m],m,-1);
    		if (r[i]<=m) modify(1,1,m,r[i],m,1);
    		if (query(1,1,m,1,m)>=0) ++ans;
    	}
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    C++ using namespace std详解
    FlexEdit强大的文本编辑器(免费的!)
    串口扩展方案总结
    LED数码引脚图
    串口扩展方案总结
    C++ using namespace std详解
    Digital Mars Compiler简介及使用
    Digital Mars Compiler简介及使用
    poj1018
    poj3536
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9122560.html
Copyright © 2020-2023  润新知