这题目看完第一段说明还没发现怎么做,看完整个的说明之后马上想到用两个数组的方法,一个储存所有客栈的色调,一个储存从1到i 的客栈中,总共多少满足可以喝咖啡的条件,然后再双重循环一个if 完事,打出来之后是这个样子。
#include<cstdio>
int htl[200010],con[200010];
int main(){
int n,k,p,spd,ans=0;
scanf("%d%d%d",&n,&k,&p);
for(int i=1;i<=n;i++){
scanf("%d%d",&htl[i],&spd);
con[i]=con[i-1]+(spd<=p?1:0);
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(htl[j]==htl[i]&&con[j]-con[i-1])
ans++;
printf("%d\n",ans);
return 0;
}
实际上我真正的第一个版本的代码是用的C++ 和结构体,然后六十分,四十分超时。我又想起以前一个因为且仅仅因为输入太久而超时的题目,于是把原代码的输入输出都换成了C 的函数,成了上面这个版本,提交后 just nothing. nothing happeed.
然后我在网上找了一下,崩溃地发现这题居然有O(n)的解法,但是最崩溃地是看到了以下的hzwer 的代码。
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int n,ys,p;
bool pd,f;
int ans=0;
int k[200001],c[200001];
int y[51]={0},s[51]={0},w[51];
memset(w,-1,sizeof(w));
cin>>n>>ys>>p;
for(int i=1;i<=n;i++)
cin>>k[i]>>c[i];
for(int i=1;i<=n;i++){
pd=0;
if(c[i]<=p)pd=1;
for(int j=i+1;j<=n;j++){
if(c[j]<=p)pd=1;
if(k[j]==k[i]){
if(pd){
pd=0;w[k[i]]=-1;y[k[i]]++;s[k[i]]+=y[k[i]];}
else{
if(w[k[i]]==-1){w[k[i]]=y[k[i]];}
s[k[i]]+=w[k[i]];
y[k[i]]++;
}
break;}
}
}
for(int i=0;i<ys;i++)
ans+=s[i];cout<<ans;
return 0;
}
我一眼扫过,看到有个双层循环,马上就心理阴暗了,这这这明明(貌似)也是O(n^2) 吧?而且他还还还那么一大堆代码,凭什么我……好吧,实际情况是他对了。我承认从来没有考虑过剪枝的威力,也从来没想过多加一堆if 可以如此显著地加快运行速度。失策了。
最后再贴上传说中的O(n), 是OpenJudge上看到的。
#include<cstdio>
int a[55],b[55],c[55];
int main(){
int n,m,k,x,sum=0,ans=0;
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<n;i++){
scanf("%d%d",&m,&x);
if(x<=k)
sum=i;
if(sum>=a[m])
b[m]=c[m];
a[m]=i;
ans+=b[m];
c[m]++;
}
printf("%d\n",ans);
return 0;
}