【NOIP2011】提高组
Day1
T1铺地毯
O(n)扫一遍,嗯,没了。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 struct node{ 5 int x,y,px,py; 6 }e[10005]; 7 int read(){ 8 int ans=0,f=1;char c=getchar(); 9 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 10 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 11 return ans*f; 12 } 13 int main(){ 14 int n=read(); 15 for(int i=1,a,b,c,d;i<=n;i++){ 16 a=read();b=read();c=read();d=read(); 17 e[i]=(node){a,b,c,d}; 18 } 19 int x=read(),y=read(); 20 int id=-1; 21 for(int i=1;i<=n;i++){ 22 node p=e[i]; 23 if(x>=p.x&&x<=p.x+p.px&&y>=p.y&&y<=p.y+p.py)id=i; 24 } 25 printf("%d",id); 26 return 0; 27 }
T2选择客栈
理解错题意WA了好几发......
题目要求的是满足col[x]==col[y]且[x,y]间存在money[i]<=p的配对数
接下来就很简单了,sum[i]表示i这种色调出现了几次,last[i]表示i这种色调最后一次出现的位置,xtd[k]表示前k个客栈中money[i]<=p的数量。
那么当xtd[i]-xtd[last[i]]-1>0时,当前客栈可与前面任何同色调的客栈配对,f[i]=sum[col[i]]。
否则,f[i]=f[last[i]]。
每次求个和就好了。
1 #include<cstdio> 2 #include<cstring> 3 #include <algorithm> 4 const int N=2e5+10; 5 int mon[N],pi[N]; 6 int read(){ 7 int ans=0,f=1;char c=getchar(); 8 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 9 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 10 return ans*f; 11 } 12 int ans=0,f[N],xtd[N],sum[55]; 13 int last[55]; 14 int main(){ 15 int n=read();read();int p=read(); 16 for(int i=1;i<=n;i++){ 17 pi[i]=read();mon[i]=read(); 18 if(!last[pi[i]])last[pi[i]]=i; 19 } 20 for(int j=1;j<=n;j++){ 21 xtd[j]=xtd[j-1]; 22 if(mon[j]<=p)xtd[j]++; 23 sum[pi[j]]++; 24 if(j==last[pi[j]])continue; 25 if(xtd[j]-xtd[last[pi[j]]-1])f[j]=sum[pi[j]]-1; 26 else f[j]=f[last[pi[j]]]; 27 ans+=f[j]; 28 last[pi[j]]=j; 29 } 30 printf("%d",ans); 31 return 0; 32 }
T3Mayan游戏
爆搜题......先弃坑,有空再补(tan90度)。
Day2
T1计算系数
数学题,很容易得到答案就是an*bm*C(k,n)-->不会去问数学老师->v->
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 typedef long long LL; 5 const int mod=1e4+7; 6 int a,b,k,n,m; 7 int ksm(LL a,int b){ 8 int res=1; 9 while(b){ 10 if(b&1)res=res*a%mod; 11 a=a*a%mod; 12 b>>=1; 13 } 14 return res; 15 } 16 LL C(int x,int y){ 17 LL res=x; 18 for(int i=2;i<=y;i++){ 19 res=res*(x-i+1)%mod*ksm(i,mod-2)%mod; 20 } 21 return res; 22 } 23 int main(){ 24 scanf("%d %d %d %d %d",&a,&b,&k,&n,&m); 25 LL ans=1; 26 ans=ans*ksm(a,n)%mod*ksm(b,m)%mod; 27 ans=ans*C(k,n)%mod; 28 printf("%lld",ans); 29 return 0; 30 }
T2聪明的质检员
二分一个W,在二分的过程中不断取极差的min就好了。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 typedef long long LL; 5 const int N=2e5+10; 6 int n,m,wi[N],vi[N],li[N],ri[N]; 7 LL s,qian[N]; 8 int sum[N]; 9 LL read(){ 10 LL ans=0,f=1;char c=getchar(); 11 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 12 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 13 return ans*f; 14 } 15 LL abs(LL a){return a>0?a:-a;} 16 LL ans; 17 bool check(LL x){ 18 LL ss=0; 19 for(int i=1;i<=m;i++){ 20 int l=li[i],r=ri[i]; 21 LL w=qian[r]-qian[l-1]; 22 int num=sum[r]-sum[l-1]; 23 ss+=w*num; 24 } 25 ans=std::min(ans,abs(ss-s)); 26 return ss<s; 27 } 28 LL l=0,r=0; 29 int main(){ 30 n=read();m=read();s=read(); 31 for(int i=1;i<=n;i++)wi[i]=read(),vi[i]=read(),r=std::max(r,(LL)wi[i]); 32 for(int i=1;i<=m;i++)li[i]=read(),ri[i]=read(); 33 ans=1e18;r++; 34 while(l<r){ 35 LL mid=(l+r)>>1; 36 qian[0]=0;sum[0]=0; 37 for(int i=1;i<=n;i++){ 38 qian[i]=qian[i-1]; 39 sum[i]=sum[i-1]; 40 if(wi[i]>=mid)qian[i]+=vi[i],sum[i]++; 41 } 42 if(check(mid))r=mid; 43 else l=mid+1; 44 } 45 printf("%lld",ans); 46 return 0; 47 }
T3观光公交
每次使用加速器的效果只有到出现车等人的情况才会结束,中间的乘客都可以享受到加速的待遇。
那么我们只要贪心地每次取出一段人数最多的使用加速器就好啦。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 const int N=1005,M=1e4+10; 5 int n,m,k; 6 int read(){ 7 int ans=0,f=1;char c=getchar(); 8 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 9 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 10 return ans*f; 11 } 12 int tim[N],l[M],fr[M],to[M],arr[N],down[N]; 13 int go[N]; 14 int ans=0,mxa=0; 15 void init(){ 16 for(int i=1;i<=n;i++)arr[i]=std::max(arr[i-1],go[i-1])+tim[i-1]; 17 } 18 int main(){ 19 n=read();m=read();k=read(); 20 for(int i=1;i<n;i++)tim[i]=read(); 21 for(int i=1;i<=m;i++){ 22 l[i]=read();fr[i]=read();to[i]=read(); 23 down[to[i]]++; 24 go[fr[i]]=std::max(go[fr[i]],l[i]); 25 } 26 init(); 27 for(int i=1;i<=m;i++)ans+=arr[to[i]]-l[i]; 28 while(k){ 29 int x=0,sum[N]; 30 memset(sum,0,sizeof(sum)); 31 for(int i=n;i>1;i--){ 32 if(tim[i-1]){ 33 sum[i-1]=down[i]; 34 if(arr[i]>go[i])sum[i-1]+=sum[i]; 35 } 36 } 37 for(int i=1;i<=n;i++) 38 if(sum[i]>sum[x])x=i; 39 if(!x)break; 40 tim[x]--;k--; 41 ans-=sum[x]; 42 init(); 43 } 44 printf("%d\n",ans); 45 return 0; 46 }