zoukankan      html  css  js  c++  java
  • bzoj 2138: stone

    Description

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

    Solution

    如果把 (m)(K_i)(n) 堆石子 (A_i) 分别拆点 , 那么实际上就是跑一个完美匹配
    假设我们钦定了这一分钟所选择的石子个数 , 判断是否合法就是判断是否存在完美匹配了
    判断是否存在完美匹配一般用到 (Hall) 定理 , 但是问题是需要枚举 (K_i) 集合的所有子集
    由于这个题目有很好的性质:右端点单调时,左端点也单调
    那么有结论: 只需要对于所有的区间 ([l,r]\,\,l,r∈[1,m]) 满足 (Hall) 定理就行了
    证明分两种情况,假设有不相邻 (i,j) 构成子集:
    1.(i,j) 所对应的区间不相交,那么 (i,j) 分别满足 (Hall) 定理就可以了
    2.(i,j) 有交,那么 ([i+1,j-1]) 一定都是被 ([L[i],R[j]]) 包含的 , 所以实际上只需要关心中间连续的一段是否满足 (Hall) 定理和整个区间 ([i,j]) 是否满足 (Hall) 定理就可以了

    设每个时间选的石子数量为 (B_i) ,剩下的就是要时刻满足:
    (sum_{i=l}^{r}B_i<=sum_{i=L[l]}^{R[r]}A_i)
    用前缀和表示:
    (SB[r]-SB[l-1]<=SA[R[r]]-SA[L[l]-1])
    (SB[R]-SA[R[r]]<=SB[l-1]-SA[L[l]-1])
    (C[i]=SB[i]-SA[R[i]],D[i]=SB[i-1]-SA[L[i]-1])
    那么就是对于所有的 (l<=r)(D[l]>=C[r])
    每一个时刻能取的上界就是 (min(D[l])-max(C[r]))
    用线段树维护一下即可,时间复杂度 (O(M*log))

    #include<bits/stdc++.h>
    #define ls (o<<1)
    #define rs (o<<1|1)
    #define sqr(x) ((x)*(x))
    using namespace std;
    template<class T>void gi(T &x){
    	int f;char c;
    	for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
    	for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
    }
    const int N=4e4+10;
    int n,a[N],b[N],id[N],m,p[N],A[N];
    struct data{int l,r,id;}q[N];
    inline bool operator <(const data &p,const data &q){return p.r<q.r;}
    struct seg{
    	int op,tr[N*4],a[N],la[N*4];
    	inline int Max(int x,int y){return op?max(x,y):min(x,y);}
    	inline void build(int l,int r,int o){
    		if(l==r){tr[o]=a[l];return ;}
    		int mid=(l+r)>>1;
    		build(l,mid,ls);build(mid+1,r,rs);
    		tr[o]=Max(tr[ls],tr[rs]);
    	}
    	inline void init(int o){op=o;build(1,m,1);}
    	inline void pushdown(int o){
    		if(!la[o])return ;
    		tr[ls]+=la[o];tr[rs]+=la[o];la[ls]+=la[o];la[rs]+=la[o];la[o]=0;
    	}
    	inline int qry(int l,int r,int o,int sa,int se){
    		if(sa<=l && r<=se)return tr[o];
    		int mid=(l+r)>>1;pushdown(o);
    		if(se<=mid)return qry(l,mid,ls,sa,se);
    		if(sa>mid)return qry(mid+1,r,rs,sa,se);
    		return Max(qry(l,mid,ls,sa,mid),qry(mid+1,r,rs,mid+1,se));
    	}
    	inline void ins(int l,int r,int o,int sa,int se,int t){
    		if(sa<=l && r<=se){tr[o]+=t;la[o]+=t;return ;}
    		int mid=(l+r)>>1;pushdown(o);
    		if(se<=mid)ins(l,mid,ls,sa,se,t);
    		else if(sa>mid)ins(mid+1,r,rs,sa,se,t);
    		else ins(l,mid,ls,sa,mid,t),ins(mid+1,r,rs,mid+1,se,t);
    		tr[o]=Max(tr[ls],tr[rs]);
    	}
    }C,D;
    int main(){
      freopen("pp.in","r",stdin);
      freopen("pp.out","w",stdout);
      int x,y,z,P;
      cin>>n>>x>>y>>z>>P;
      for(int i=1;i<=n;i++)a[i]=(1ll*sqr(i-x)+sqr(i-y)+sqr(i-z))%P;
      cin>>m;
      if(!m)return 0;
      cin>>b[1]>>b[2]>>x>>y>>z>>P;
      for(int i=3;i<=m;i++)b[i]=(x*b[i-1]+y*b[i-2]+z)%P;
      for(int i=1;i<=m;i++)gi(q[i].l),gi(q[i].r),q[i].id=i;
      sort(q+1,q+m+1);n=0;
      for(int i=1,j=1;i<=m;i++){
    	  for(j=max(j,q[i].l);j<=q[i].r;j++)A[id[j]=++n]=a[j];
    	  q[i].l=id[q[i].l];q[i].r=id[q[i].r];p[q[i].id]=i;
      }
      for(int i=1;i<=n;i++)A[i]+=A[i-1];
      for(int i=1;i<=m;i++)C.a[i]=-A[q[i].r],D.a[i]=-A[q[i].l-1];
      C.init(1);D.init(0);
      for(int i=1;i<=m;i++){
    	  x=p[i];
    	  int rm=C.qry(1,m,1,p[i],m),lm=D.qry(1,m,1,1,p[i]);
    	  int res=min(b[i],lm-rm);
    	  printf("%d
    ",res);
    	  C.ins(1,m,1,p[i],m,res);
    	  if(p[i]<m)D.ins(1,m,1,p[i]+1,m,res);
      }
      return 0;
    }
    
    
  • 相关阅读:
    appium自动化测试搭建
    How to install Qt Creator on Ubuntu 18.04
    Luci
    OpenWrt 根文件系统启动过程分析
    shell 杂烩
    OpenWrt Luci 调试日志输出的一种方法
    jQuery实现购物车计算价格的方法
    js实现购物车添加,减少数量
    golang-键盘录入数据
    JAVA存储机制(栈、堆、方法区详解)
  • 原文地址:https://www.cnblogs.com/Yuzao/p/9186858.html
Copyright © 2011-2022 走看看