上星期打了人生中第一场bestcoder,死得很惨。
最简单的T1居然被人hack掉了,哎。
T4T5不会做,只放前三题的题解。
T1:Price List
给定
n
家商店的物品价格(每家商店只卖一种商品),其中第
本题十分简单,只需先求出所有数的和 sum ,如果 q>sum 那么肯定记多了。
时间复杂度为 Θ(n) 。
但是需要注意的是本题的数据规模为 1≤n≤100000 , 1≤vi≤100000 ,那么
//yhf
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int t; cin>>t;
for ( ; t>0; t--)
{
int n,m; scanf("%d%d",&n,&m);
long long sum=0;
for (int i=0; i<n; i++)
{
int v; scanf("%d",&v);
sum+=v;
}
for (int i=0; i<m; i++)
{
long long s; scanf("%I64d",&s);
if (s>sum) cout<<1; else cout<<0;
}
cout<<endl;
}
return 0;
}
T2:NanoApe Loves Sequence
给定一个长度为
n
的数列,任意删去一个数后可得到一个新数列,我们可以计算出所有相邻两数的差的绝对值的最大值。显然这个最大值会随着被删的数改变而改变,假如全部数被删除的概率是相等的话,求差的绝对值的最大值的期望与
首先,lkb数学不好,期望是个什么鬼?
用准确的数学语言lkb不会描述,不过通过推算样例,猜测这题里面把删去每个数后所有相邻两数的差的绝对值的最大值相加就是解,果然是对的。(不过lkb还是不知道什么是期望,似乎就是每次可能结果的概率乘以其结果的总和?)
这题的做法又是简单的预处理:求出前
i
个数里相邻差值的最大值
问题得解。时间复杂度为 Θ(n) 。
//yhf
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define R(x) scanf("%d",&x)
using namespace std;
const int ML=100000;
int a[ML+10],ml[ML+10],mr[ML+10];
int main()
{
int t; R(t);
for ( ; t>0; t--)
{
int n; R(n);
for (int i=1; i<=n; i++) R(a[i]);
ml[0]=ml[1]=mr[n]=mr[n+1]=0;
mr[n-1]=abs(a[n]-a[n-1]);
for (int i=2; i<=n; i++)
ml[i]=max(ml[i-1],abs(a[i]-a[i-1]));
for (int i=n-2; i>0; i--)
mr[i]=max(mr[i+1],abs(a[i]-a[i+1]));
a[0]=a[2]; a[n+1]=a[n-1];
long long ans=0;
for (int i=1; i<=n; i++)
{
int nt=abs(a[i+1]-a[i-1]);
int ma=max(ml[i-1],mr[i+1]);
// cout<<max(nt,ma)<<endl;
ans+=max(nt,ma);
}
cout<<ans<<endl;
}
return 0;
}
T3:给定一个长度为
n
的数列和一个数
这题一看区间第 k 大,lkb的第一反应是用各种奇葩数据结构进行维护,但是仔细思考后发现并不需要这么麻烦。
我们可以用单调队列来维护这个区间,显然如果对于某个区间
于是对于每一个
i
,用单调队列求出最小的
官方标答如下:
将不小于 m 的数看作1,剩下的数看作0,那么只要区间内1的个数不小于
k 则可行,枚举左端点,右端点可以通过two-pointer求出。
时间复杂度 Θ(n) 。
参考程序:
//yhf
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
int a[200010];
int main()
{
int t; scanf("%d",&t);
for ( ; t>0; t--)
{
int n,k,m; scanf("%d%d%d",&n,&m,&k);
for (int i=0; i<n; i++) scanf("%d",&a[i]);
long long ans=0;
int sm=0,j=0;
for (int i=0; i<n; i++)
{
for ( ; j<n && sm<k; j++)
if (a[j]>=m) sm++;
//cout<<j<<endl;
if (sm>=k) ans+=n-j+1;
if (a[i]>=m) sm--;
}
cout<<ans<<endl;
}
}