这次的校内训练有4题,难度适中,成绩也不错.令人诧异的是这次的四题居然都是原题.尽管如此,我还是有比较多的失误.
第一题原题在洛谷1360,网址:https://www.luogu.org/problem/show?pid=1360
题意大致是给出n个01串(不超过m位,压成整数)求这些串中最长的子串满足对于每一位,这个字串每个元素这位是1的个数的和相同.
比如:1110010 1001
1111001 1100
1010100 (竖着看从左往右7个整数)中有第3到第6个:1010 每一位1的个数都是2,所以满足
n<=100000,m<=30
那么,怎么解决呢?
凭感觉,我们前缀和一下,发现只要每行的某一位和另一位差为一个定值.进一步,我们考虑每行用和第一行的差距来代替,那么就等价于每行某一位和另一位相等,也就是找到完全相同的两列.
要找完全相同的距离最大的两列,就只要用stl的map或者哈希一下就好了.
囿于我不会写map(好好学习stl!)以及懒得打哈希,代码就不打了.考试时交了个暴力居然有70分,吐槽一下数据.
第二题原题NOIP2015跳石头,原题答案-1,百度一堆题解,这里就不赘述了.只是我只拿了30分,是四题中最低的,原因就是冒险用了不保险的二分方式导致死循环,一个字:浪!
代码如下:
#include<cstdio>
#include<algorithm>
int n,m,k,a[50002],l=0,r=1000000000,mid=(l+r)/2;
bool check(int x)
{
int lst=0,cnt=0;
for(int i=1;i<=n;i++)if((a[i]-a[lst])>x)lst=i,cnt++;
return cnt>=n-k;
}
int main()
{
scanf("%d%d%d",&m,&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);a[++n]=m;
std::sort(a+1,a+n+1);
while(l<r)
{
if(check(mid))l=mid+1;
else r=mid;
mid=(l+r)>>1;
}
printf("%d",mid-1);
return 0;
}
第三题题意是给定一堆任务,有限时和奖励,每单位时间只能做一个任务,求奖励最大值,据说是原题,反正不管他,比较水.
这题考场上随脑想了个贪心,就是从后往前扫时间,限时就变成了任务开启时间,然后直接按奖励贪心堆维护就好了
代码如下:
#include<cstdio>
#include<algorithm>
#include<queue>
int a[100001],b[100001],o[100001],n,j=1;
long long ans;
std::priority_queue<int>h;
bool cmp(int x,int y){return a[x]>a[y];}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]),o[i]=i;
std::sort(o+1,o+n+1,cmp);
for(int i=a[o[1]];i;i--)
{
for(;a[o[j]]==i;j++)h.push(b[o[j]]);
if(!h.empty())ans+=h.top(),h.pop();
}
printf("%lld",ans);
return 0;
}
但是正确性能保证,时间嘛...TLE了一个点,因为stl的pq实在是常数太大啦!我又开始想要不要学stl了...
第四题是裸的MST,直接按照图跑一遍就好了,而且数据范围很小,prim堆优化都不用开,kruskal因为边数太多更是浪费.轻松AC
代码:
#include<cstdio>
int a[301][301],n,val[301],ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[0][i]),a[i][0]=a[0][i];
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)val[i]=a[0][i];
for(int i=1;i<=n;i++)
{
int Min=-1;
for(int j=1;j<=n;j++)if(val[j]!=0)if(Min==-1)Min=j;else if(val[Min]>val[j])Min=j;
ans+=val[Min];
for(int j=1;j<=n;j++)val[j]=val[j]>a[Min][j]?a[Min][j]:val[j];
}
printf("%d",ans);
return 0;
}
这场比赛还算是春风得意吧.才有时间迅速调完写完博.