[NOIP2011]刷水
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NOIP2011]刷水相关的知识,希望对你有一定的参考价值。
前几天做了NOIP2011的题,感觉不是那么难。
这边先做了两天的前两题,T3还没打。
D1T1:顺次读入,分别判断是否覆盖即可,照例大水:
#include<cstdio> int x,y,a[10001],b[10001],c[10001],d[10001],n,ans=-1; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d%d%d",a+i,b+i,c+i,d+i); scanf("%d%d",&x,&y); for(int i=1;i<=n;i++) if(a[i]<=x&&b[i]<=y&&c[i]+a[i]>=x&&d[i]+b[i]>=y)ans=i; printf("%d",ans); return 0; }
D1T2:一边扫过去,对于每家客栈,我们记下前一家相同色调的客栈,前一家能去的咖啡店,之前有多少家可以和这间客栈搭配和这是第几间该色调的客栈,然后如果前一家色调相同的客栈编号在前一家能去的咖啡店之前,说明这之前的客栈都能去,把可搭配客栈数更新后加入答案,否则直接加入答案。
代码如下:
#include<cstdio> using namespace std; int n,p,t[200001],h[51],ans,l[51],lst[51]; int main() { scanf("%d%*d%d",&n,&p); for(int i=0;i<=50;i++)lst[i]=1; for(int i=1;i<=n;i++) { int w,c; scanf("%d%d",&c,&w); t[i]=t[i-1]+(w<=p); if(t[i]!=t[lst[c]-1])h[c]=l[c]; l[c]++; ans+=h[c]; if(w<=p)h[c]=l[c]; lst[c]=i; } printf("%d",ans); return 0; }
D2T1:用杨辉三角计算组合数然后用二项式定理直接出解:
#include<cstdio> const int mod=10007; int a,b,k,n,m,C[1002][1002],aa=1,bb=1; void calC() { C[1][1]=1; for(int i=2;i<=1001;i++) for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } int main() { calC(); scanf("%d%d%d%d%d",&a,&b,&k,&n,&m); a%=mod;b%=mod; for(int i=1;i<=n;i++)aa=(aa*a)%mod; for(int i=1;i<=m;i++)bb=(bb*b)%mod; printf("%d",((aa*bb%mod)*C[k+1][n+1])%mod); return 0; }
D2T2:使和标准最近,而且是单调递减,容易想到用二分答案+check
二分就不说了。check中我们要O(m)计算m个区间的sigma,可以对于二分出的x计算从1到n能加入答案的计算前缀和然后轻松处理。
要注意防止爆long long,这边处理方法是加个最优上限maxn,否则一定不优。
代码如下:
#include<cstdio> const long long maxn=10000000000000ll; long long mn(long long x,long long y){return x<y?x:y;} long long s[200001],ans=maxn,sa,v[200001],w[200001],sum[200001],l[200001],r[200001],ll,rr,n,m,mid; bool check(long long x) { long long tt=0; for(int i=1;i<=n;++i) sum[i]=sum[i-1]+(w[i]>=x), s[i]=s[i-1]+(w[i]>=x?v[i]:0); for(int i=1;i<=m;++i) { tt+=(sum[r[i]]-sum[l[i]-1])*(s[r[i]]-s[l[i]-1]); if(tt>maxn)return 0; } ans=mn(-mn(tt-sa,sa-tt),ans); return tt<=sa; } void bina() { ll=0;rr=1000000; while(ll<rr) { mid=(ll+rr)/2; check(mid)?rr=mid:ll=mid+1; } } int main() { scanf("%lld%lld%lld",&n,&m,&sa); for(int i=1;i<=n;++i)scanf("%lld%lld",w+i,v+i); for(int i=1;i<=m;++i)scanf("%lld%lld",l+i,r+i); bina(); check(mid-1);check(mid); printf("%lld",ans); return 0; }
以上是关于[NOIP2011]刷水的主要内容,如果未能解决你的问题,请参考以下文章