[Hall定理 + 线段树] LibreOJ#6062. 「2017 山东一轮集训 Day2」Pair

可以先对 B 排序,然后 A 中的每个数能匹配的 B 中的元素都是一个后缀的形式。
对于一个 A 元素的集合是否与 B 有完美匹配呢? 可以考虑Hall定理,随便选一个B中的集合S:
由于图的特殊性,N(S)=N(S) ,也就是说只要所有后缀都满足 N(S)|S| ,则任意集合都满足。
这样就很简单了,只要满足对于所有 i , N(i)i 即可。
枚举所有可能子段,用线段树维护 N(i)i 的最小值,就好了。

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=200005;
int n,m,H,ans,a[maxn],b[maxn],L[maxn];
struct node{
    int _min,tag; node* ch[2];  
    node(int x=0){_min=x;tag=0;ch[0]=ch[1]=0;}
    void Plus(int x){ _min+=x; tag+=x; }
    void pushdown(){ if(tag) ch[0]->Plus(tag), ch[1]->Plus(tag), tag=0; }
    void maintain(){ _min=min(ch[0]->_min,ch[1]->_min); }
} *root, base[maxn*2], *p_top=base;
typedef node* P_node;
void Updata(P_node p,int L,int R,int qL,int qR,int val){
    if(R<qL||qR<L||qL>qR) return;
    if(qL<=L&&R<=qR){ p->Plus(val); return; }
    int mid=(L+R)>>1; p->pushdown();
    Updata(p->ch[0],L,mid,qL,qR,val); Updata(p->ch[1],mid+1,R,qL,qR,val);
    p->maintain();
}
P_node newnode(){ *p_top=node(2e9); return p_top++; }
P_node Build(int L,int R){
    P_node p=newnode();
    if(L==R){ p->_min=-L; return p; }
    int mid=(L+R)>>1;
    p->ch[0]=Build(L,mid); p->ch[1]=Build(mid+1,R);
    p->maintain(); return p;
}
int Find(int x){
    int L=1,R=m,res=m+1;
    while(L<=R){ int mid=(L+R)>>1; if(x<=b[mid]) R=mid-1, res=mid; else L=mid+1; }
    return res;
}
int main(){
    freopen("loj6062.in","r",stdin);
    freopen("loj6062.out","w",stdout);
    scanf("%d%d%d",&n,&m,&H);
    for(int i=1;i<=m;i++) scanf("%d",&b[i]);
    sort(b+1,b+1+m); 
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),L[i]=Find(H-a[i]); 
    if(m>n) return puts("0"),0;
    root=Build(1,m);
    for(int i=1;i<=m;i++) Updata(root,1,m,L[i],m,1);
    for(int i=m;i<=n;i++,Updata(root,1,m,L[i],m,1),Updata(root,1,m,L[i-m],m,-1)) 
    if(root->_min>=0) ans++;
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值