【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个,那么对于任意$1\le l\le r\le m$,需要满足:

$\sum\limits_{i=l}^r B[i]\le \sum\limits_{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\n",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;
}

原文地址:https://www.cnblogs.com/CQzhangyu/p/8469010.html

时间: 2024-11-06 07:15:58

【BZOJ2138】stone Hall定理+线段树的相关文章

Codeforces Round #FF (Div. 2) E. DZY Loves Fibonacci Numbers(斐波那契的定理+线段树)

/* 充分利用了菲波那切数列的两条定理: ①定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3). 有F[n] = b * fib[n - 1] + a * fib[n - 2](n≥3),其中fib[i]为斐波那契数列的第 i 项. ②定义F[1] = a, F[2] = b, F[n] = F[n - 1] + F[n - 2](n≥3). 有F[1] + F[2] + -- + F[n] = F[n + 2] - b 这题还有一个事实,

[CTSC2017]游戏(Bayes定理,线段树)

传送门:http://uoj.ac/problem/299 题目良心给了Bayes定理,但对于我这种数学渣来说并没有什么用. 先大概讲下相关数学内容: 1.定义:$P(X)$ 表示事件$X$发生的概率,$E(X)$表示随机变量$X$的期望值,$P(A|B)$表示已知$B$发生,$A$发生的概率,$P(AB)$表示$A$和$B$同时发生的概率. 2.条件概率公式: $\begin{aligned}P(A|B)=\frac{P(AB)}{P(B)}\end{aligned}$. 由$P(B)P(A|

【题解】 AtCoder ARC 076 F - Exhausted? (霍尔定理+线段树)

题面 题目大意: 给你\(m\)张椅子,排成一行,告诉你\(n\)个人,每个人可以坐的座位为\([1,l]\bigcup[r,m]\),为了让所有人坐下,问至少还要加多少张椅子. Solution: 为什么加椅子?我们可以在最左边或最右边一直加直到人人都有座位. 首先这道题目抽象成二分图很简单,然后我们可以只要求解出人与座位的最大匹配是多少,总人数减去即可,但跑二分图最大匹配显然会超时,我们就可以往霍尔定理方面想. 然后你还需要知道一个霍尔定理推论:假设某个人的集合为\(X\),这个集合所对应的

【AtCoder ARC076】F Exhausted? 霍尔定理+线段树

题意 N个人抢M个椅子,M个椅子排成一排 ,第i个人只能坐[1,Li]∪[Ri,M],问最多能坐多少人 $i$人连边向可以坐的椅子构成二分图,题意即是求二分图最大完美匹配,由霍尔定理,答案为$max(|X|-\omega(X))$,$X$为人的集合,$\omega(X)$可以表示为$[1,l] \cup[r,M]$,所以可以枚举$\omega(X)$也就是$(l,r)$,求出最大的$|X|$,也就是满足$L_i\le l \land r \le R_i$的$i$的数量,也就是平面上以$(l,r)

【题解】 bzoj1135: [POI2009]Lyz (线段树+霍尔定理)

题面戳我 Solution 二分图是显然的,用二分图匹配显然在这个范围会炸的很惨,我们考虑用霍尔定理. 我们任意选取穿\(l,r\)的号码鞋子的人,那么这些人可以穿的鞋子的范围是\(l,r+d\),这个时候我们可以根据霍尔定理得出满足人人有鞋子穿的时候的式子是 令\(sum[i]\)表示穿\(i\)号鞋子的人数 \[\Sigma^r_{i=l} sum[i] \leq (r-l+1+d)*k\] 我们把这个式子整理下: \[\Sigma^r_{i=l} (sum[i]-k) \leq d*k\]

线段树区间更新 费马小定理|魔豆传奇

程序设计:魔豆传奇 <魔豆传奇>是2004年的一部动画片.里面有很多奇怪的魔豆,具有奇特且强大的能力. 偶然间,蒜头君获得了一排已经发芽的魔豆,每株的最初高度为ai . 蒜头君每天都会选择对一段区间的魔豆浇水,或查看一段区间魔豆的高度和. 魔豆每一次被浇水,其高度会变为之前高度的立方. 也就是说,蒜头君有两种操作: 1.使序列中下标在区间[L,R] 中的每个数变成自己的立方. 2.查询序列中下标在区间[L,R]中的数值和. 由于魔豆高度过大,查询时你需要输出数值和对1046513837 取模的

HDU 3911 Black And White(线段树区间合并)

Problem Description There are a bunch of stones on the beach; Stone color is white or black. Little Sheep has a magic brush, she can change the color of a continuous stone, black to white, white to black. Little Sheep like black very much, so she wan

codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)

In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 = 1; F2 = 1; Fn = Fn - 1 + Fn - 2 (n > 2). DZY loves Fibonacci numbers very much. Today DZY gives you an array consisting of n integers: a1, a2, ...,

Devour Magic 线段树

点击打开链接 Devour Magic Time Limit: 2000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 In Warcraft III, Destroyer is a large flying unit that must consume magic to sustain its mana. Breaking free of the obsidian stone that holds them, these monstrous creatur