9.10校内训练

  这次的校内训练有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;
}

 这场比赛还算是春风得意吧.才有时间迅速调完写完博.

posted @ 2017-09-11 21:54  qrc  阅读(209)  评论(0编辑  收藏  举报