BZOJ2138 : stone

本文介绍如何使用Hall定理判断完美匹配的可能性,并通过线段树维护区间信息来解决相关问题。采用特定的数据结构优化算法,实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

根据Hall定理,若存在一个区间满足内部需求数$>$内部石子数,则不存在完美匹配。

由于区间互不包含,所以设:

$a[i]$表示右端点$\leq i$的区间的容量之和。

$b[i]$表示左端点$\leq i$的区间的容量之和。

$s[i]$表示前$i$个位置的石子数之和。

则区间$[l,r]$的:

石子数$=s[r]-s[l-1]$。

需求数$=a[r]-b[l-1]$。

即对于任意$0\leq i<j\leq n$,要满足:

$\min((s[j]-a[j])-(s[i]-b[i]))\geq 0$

$f[i]=s[i]-a[i]$

$g[i]=s[i]-b[i]$

考虑$[l,r]$区间需求数为$k$时对匹配的影响:

$f[r..n]-=k$

$g[l..n]-=k$

那么当$k$取$\min(f[\geq r])-\max(g[<l])$时刚好满足所有限制。

线段树维护即可。

时间复杂度$O(m\log n)$。

 

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=40010,M=131100,inf=~0U>>1;
int n,m,i,x,y,z,P,a[N],f[M],g[M],tf[M],tg[M];
inline void tagf(int x,int y){f[x]+=y;tf[x]+=y;}
inline void tagg(int x,int y){g[x]+=y;tg[x]+=y;}
inline void pb(int x){
  if(tf[x])tagf(x<<1,tf[x]),tagf(x<<1|1,tf[x]),tf[x]=0;
  if(tg[x])tagg(x<<1,tg[x]),tagg(x<<1|1,tg[x]),tg[x]=0;
}
inline void up(int x){
  f[x]=min(f[x<<1],f[x<<1|1]);
  g[x]=max(g[x<<1],g[x<<1|1]);
}
void build(int x,int a,int b){
  if(a==b){f[x]=g[x]=::a[a];return;}
  int mid=(a+b)>>1;
  build(x<<1,a,mid),build(x<<1|1,mid+1,b);
  up(x);
}
void changef(int x,int a,int b,int c,int d,int p){
  if(c<=a&&b<=d){tagf(x,-p);return;}
  pb(x);
  int mid=(a+b)>>1;
  if(c<=mid)changef(x<<1,a,mid,c,d,p);
  if(d>mid)changef(x<<1|1,mid+1,b,c,d,p);
  up(x);
}
void changeg(int x,int a,int b,int c,int d,int p){
  if(c<=a&&b<=d){tagg(x,-p);return;}
  pb(x);
  int mid=(a+b)>>1;
  if(c<=mid)changeg(x<<1,a,mid,c,d,p);
  if(d>mid)changeg(x<<1|1,mid+1,b,c,d,p);
  up(x);
}
int askf(int x,int a,int b,int c,int d){
  if(c<=a&&b<=d)return f[x];
  pb(x);
  int mid=(a+b)>>1,t=inf;
  if(c<=mid)t=askf(x<<1,a,mid,c,d);
  if(d>mid)t=min(t,askf(x<<1|1,mid+1,b,c,d));
  return t;
}
int askg(int x,int a,int b,int c,int d){
  if(c<=a&&b<=d)return g[x];
  pb(x);
  int mid=(a+b)>>1,t=-inf;
  if(c<=mid)t=askg(x<<1,a,mid,c,d);
  if(d>mid)t=max(t,askg(x<<1|1,mid+1,b,c,d));
  return t;
}
int main(){
  scanf("%d%d%d%d%d",&n,&x,&y,&z,&P);
  for(i=1;i<=n;i++)a[i]=(1LL*(i-x)*(i-x)+1LL*(i-y)*(i-y)+1LL*(i-z)*(i-z))%P,a[i]+=a[i-1];
  build(1,0,n);
  scanf("%d%d%d%d%d%d%d",&m,&a[1],&a[2],&x,&y,&z,&P);
  for(i=3;i<=m;i++)a[i]=(1LL*x*a[i-1]+1LL*y*a[i-2]+z)%P;
  for(i=1;i<=m;i++){
    scanf("%d%d",&x,&y);
    printf("%d\n",z=min(askf(1,0,n,y,n)-askg(1,0,n,0,x-1),a[i]));
    changef(1,0,n,y,n,z);
    changeg(1,0,n,x,n,z);
  }
  return 0;
}

  

资源下载链接为: https://pan.quark.cn/s/f989b9092fc5 HttpServletRequestWrapper 是 Java Servlet API 中的一个工具类,位于 javax.servlet.http 包中,用于对 HttpServletRequest 对象进行封装,从而在 Web 应用中实现对 HTTP 请求的拦截、修改或增强等功能。通过继承该类并覆盖相关方法,开发者可以轻松地自定义请求处理逻辑,例如修改请求参数、添加请求头、记录日志等。 参数过滤:在请求到达处理器之前,可以对请求参数进行检查或修改,例如去除 URL 编码、过滤敏感信息或进行安全检查。 请求头操作:可以修改或添加请求头,比如设置自定义的 Content-Type 或添加认证信息。 请求属性扩展:在原始请求的基础上添加自定义属性,供后续处理使用。 日志记录:在处理请求前记录请求信息,如 URL、参数、请求头等,便于调试和监控。 跨域支持:通过添加 CORS 相关的响应头,允许来自不同源的请求。 HttpServletRequestWrapper 通过继承 HttpServletRequest 接口并重写其方法来实现功能。开发者可以在重写的方法中添加自定义逻辑,例如在获取参数时进行过滤,或在读取请求体时进行解密。当调用这些方法时,实际上是调用了包装器中的方法,从而实现了对原始请求的修改或增强。 以下是一个简单的示例,展示如何创建一个用于过滤请求参数的包装器: 在 doFilter 方法中,可以使用 CustomRequestWrapper 包装原始请求: 这样,每当调用 getParameterValues 方法时,都会先经过自定义的过滤逻辑。 HttpServletRequestWrapper 是 Java Web 开发中一个强大的工具,它提供了灵活的扩展性,允许开发者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值