• 【BZOJ2138】stone Hall定理+线段树


    【BZOJ2138】stone

    Description

    话说Nan在海边等人,预计还要等上M分钟。为了打发时间,他玩起了石子。Nan搬来了N堆石子,编号为1到N,每堆包含Ai颗石子。每1分钟,Nan会在编号在[Li,Ri]之间的石堆中挑出任意Ki颗扔向大海(好疼的玩法),如果[Li,Ri]剩下石子不够Ki颗,则取尽量地多。为了保留扔石子的新鲜感,Nan保证任意两个区间[Li,Ri]和[Lj,Rj],不会存在Li<=Lj&Rj<=Ri的情况,即任意两段区间不存在包含关系。可是,如果选择不当,可能无法扔出最多的石子,这时NN就会不高兴了。所以他希望制定一个计划,他告诉你他m分钟打算扔的区间[Li,Ri]以及Ki。现在他想你告诉他,在满足前i-1分钟都取到你回答的颗数的情况下,第i分钟最多能取多少个石子。

    Input

    第一行正整数N,表示石子的堆数;
    第二行正整数x,y,z,P,(1<=x,y,z<=N;P<=500) 
    有等式A[i]=[(i-x)^2+(i-y)^2+(i-z)^2] mod P;
    第三行正整数M,表示有M分钟;
    第四行正整数K[1],K[2],x,y,z,P,(x,y,z<=1000;P<=10000) 
    有等式K[i]=(x*K[i-1]+y*K[i-2]+z)mod P。
    接下来M行,每行两个正整数L[i],R[i]。
    N<=40000   M<=N   1<=L[i]<=R[i]<=N   A[i]<=500

    Output

    有M行,第i行表示第i分钟最多能取多少石子。

    Sample Input

    5
    3 2 4 7
    3
    2 5 2 6 4 9
    2 4
    1 2
    3 5

    Sample Output

    2
    5
    5
    【样例说明】
    石子每堆个数分别为0,5,2,5,0。
    第1分钟,从第2到第4堆中选2个;
    第2分钟,从第1到第2堆中选5个;
    第3分钟,从第3到第5堆中选8个,但最多只能选5个。

    题解:如果把每堆石子拆成$A_i$个,将询问拆成$K_i$个,则原题可看成一个二分图最大匹配的模型。这里要应用到Hall定理。

    Hall定理:两个集合$X$和$Y$进行匹配,最大匹配为$|X|$的充要条件是:对于X的任意一个子集S,设Y中与S相邻的点集为T,满足$|S|le |T|$。

    但是定理里面写的是任意一个子集,而我们想把它转化成区间上的形式,不难想到:在本题中,我们是否可以不枚举所有石子的所有子集,而是只枚举所有的区间是否满足条件呢?答案是肯定的,证明也非常简单:

    首先,如果我们取了一个询问,但是没有全取,显然这种情况是不需要讨论的,因为同一个询问中每个石子的邻集都是相同的,如果全取完满足条件的话不全取完也一定满足条件。

    其次,如果我们取的询问不是连续的一段区间,这种情况也是没有意义的。因为题中满足询问的r随着l增大而增大,如果我们选的两个的询问段不相交,则我们完全可以分开考虑,看每一段是否满足条件即可。

    然后就轻松多啦!我们将询问按位置排序,并剔除掉所有没有用到的堆,设第i个询问我们取了Bi个,那么对于任意$1le lle rle m$,需要满足:

    $sumlimits_{i=l}^r B[i]le sumlimits_{i=L[l]}^{R[r]}A[i]$

    改成前缀和的形式就是:

    $sb[r]-sb[l-1]le sa[R[r]]-sa[L[l]-1]$
    $sb[r]-sa[R[r]]le sb[l-1]-sa[L[l]-1]$

    我们设$C[i]=sb[i]-sa[R[i]],D[i]=sb[i-1]-sa[L[i]-1]$,则限制就变成了
    $C[r]le D[l]$

    所以,我们只需要按时间序处理询问,然后在线段树上统计右面C的最大值以及左边D的最小值就能得到当前B的最大值了。然后将i...n的C都+B,i+1...n的D都+B即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    const int maxn=40010;
    int X,Y,Z,P;
    int n,m;
    int L[maxn],R[maxn],A[maxn],B[maxn],ref[maxn],sa[maxn],sb[maxn],p[maxn],C[maxn],D[maxn];
    struct node
    {
    	int l,r,org;
    }q[maxn];
    struct sag
    {
    	int s[maxn<<2],tag[maxn<<2],flag;
    	inline int MX(int a,int b)
    	{
    		if(flag==0)	return max(a,b);
    		else	return min(a,b);
    	}
    	inline void pushdown(int x)
    	{
    		if(tag[x])	s[lson]+=tag[x],s[rson]+=tag[x],tag[lson]+=tag[x],tag[rson]+=tag[x],tag[x]=0;
    	}
    	void build(int l,int r,int x)
    	{
    		if(l==r)
    		{
    			if(flag==0)	s[x]=C[l];
    			else	s[x]=D[l];
    			return ;
    		}
    		int mid=(l+r)>>1;
    		build(l,mid,lson),build(mid+1,r,rson);
    		s[x]=MX(s[lson],s[rson]);
    	}
    	void updata(int l,int r,int x,int a,int b,int c)
    	{
    		if(a<=l&&r<=b)
    		{
    			s[x]+=c,tag[x]+=c;
    			return ;
    		}
    		pushdown(x);
    		int mid=(l+r)>>1;
    		if(a<=mid)	updata(l,mid,lson,a,b,c);
    		if(b>mid)	updata(mid+1,r,rson,a,b,c);
    		s[x]=MX(s[lson],s[rson]);
    	}
    	int query(int l,int r,int x,int a,int b)
    	{
    		if(a<=l&&r<=b)	return s[x];
    		pushdown(x);
    		int mid=(l+r)>>1;
    		if(b<=mid)	return query(l,mid,lson,a,b);
    		if(a>mid)	return query(mid+1,r,rson,a,b);
    		return MX(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
    	}
    }SC,SD;
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    bool cmp(const node &a,const node &b)
    {
    	return a.l<b.l;
    }
    int main()
    {
    	n=rd();
    	int i,j;
    	X=rd(),Y=rd(),Z=rd(),P=rd();
    	for(i=1;i<=n;i++)	A[i]=((i-X)*(i-X)+(i-Y)*(i-Y)+(i-Z)*(i-Z))%P;
    	m=rd();
    	if(!m)	return 0;
    	B[1]=rd(),B[2]=rd(),X=rd(),Y=rd(),Z=rd(),P=rd();
    	for(i=3;i<=m;i++)	B[i]=(X*B[i-1]+Y*B[i-2]+Z)%P;
    	for(i=1;i<=m;i++)	q[i].l=rd(),q[i].r=rd(),q[i].org=i;
    	sort(q+1,q+m+1,cmp);
    	for(i=1,j=n=0;i<=m;i++)
    	{
    		for(j=max(j,q[i].l);j<=q[i].r;j++)	A[++n]=A[j],ref[j]=n;
    		L[q[i].org]=ref[q[i].l],R[q[i].org]=ref[q[i].r],p[q[i].org]=i;
    	}
    	for(i=1;i<=n;i++)	sa[i]=sa[i-1]+A[i];
    	for(i=1;i<=m;i++)	C[p[i]]=-sa[R[i]],D[p[i]]=-sa[L[i]-1];
    	SC.flag=0,SD.flag=1,SC.build(1,m,1),SD.build(1,m,1);
    	for(i=1;i<=m;i++)
    	{
    		int rm=SC.query(1,m,1,p[i],m),ln=SD.query(1,m,1,1,p[i]);
    		B[i]=min(B[i],ln-rm);
    		printf("%d
    ",B[i]);
    		SC.updata(1,m,1,p[i],m,B[i]);
    		if(p[i]!=m)	SD.updata(1,m,1,p[i]+1,m,B[i]);
    	}
    	return 0;
    }
  • 相关阅读:
    XenServer 7 上Linux单用户模式下修改密码
    python pysnmp使用
    处理一则MySQL Slave环境出现ERROR 1201 (HY000): Could not initialize master info structure的案例。
    H3C交换机端口聚合
    H3C交换机密码策略
    使用Chrome远程调试GenyMotion上的WebView程序
    CefGlue在WinXP下闪退的排查方法
    Visual Studio 2015 开发Android Cordova出现unsupported major minor version 52.0错误的解决方法
    股票涨跌预测器
    javascript模块化编程-详解立即执行函数表达式IIFE
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8469010.html
Copyright © 2020-2023  润新知