[NOIP2011]刷水
阿新 • • 發佈:2017-05-07
using 處理 can include 處理方法 ans 過去 urn pri
前幾天做了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> usingnamespace 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]刷水