AHOI2018个人复习回顾

2018的AHOI是笔者初一是打的一场比赛,但是结果很使人哀伤,无奈爆零
但是时间不许我们徘徊,我们要有希望——转眼间AHOI2019就要到了——我要一血前耻!

BB一番后现在就要开始正题了(题号不一定正确见谅)

T1:报名签到 https://www.luogu.org/problemnew/show/P4445(自己看去,懒得复制整理了
这题很水但是我当时还是爆零
这是比较简单的一道题目,题意也是比较容易理解的,为了不发生冲突,我们就去选相邻两者中比较大的一方,这样是两全其美的,但是要注意开long long。(long貌似也可以
下面是代码:

#include <bits/stdc++.h>
using namespace std;

long long ans;
int n;
int a[100009];

int main()
{
	cin>>n;   //输入
	for (int i = 1; i <= n; i++)
		cin>>a[i];
	
	for (int i = 1; i < n; i++)
		ans += max(a[i],a[i+1]);    //计算
		
	cout<<ans;    //输出
	
	return 0;
}

T2:根式化简 https://www.luogu.org/problemnew/show/P4446
此题本人表示不会
这题个人感觉很难,luogu里的题解都是数论搭配其他算法或是什么玄学东西的,反正我不会,我对数论一无所知呀,只能掏出自己烂的可怜的暴力了。。。思路就不说了,那么烂,肯定都懂。
代码:

#include <bits/stdc++.h>
using namespace std;

long a,x[100009],n,ans;

int judge(int z)
{
    for (int i = 1; i <= (int)sqrt(z); i++)
        if (i * i * i == z) 
        {
            a = i;
            
            return true;
        }
    
    return false;
}

int main()
{
    cin>>n;
    for (int i = 1; i <= n; i++)
        cin>>x[i];
    
        for (int i = 1; i <= n; i++)
            {
                ans = 1;
            
                for (int b = 1; b <= (int)sqrt(x[i]); b++)
                    if (x[i] % b == 0 && judge(x[i]/b))
                        ans = max(ans,a);
            
                cout<<ans<<endl;
            }
    return 0;
}

T3:分组 https://www.luogu.org/problemnew/show/P4447
这题笔者在思考了一段时间后还是有意思理解的(我看题解了,反正能搞懂就行
刚开始的几次是60分的,思路也很简单,就是模拟贪心的思想,维护多个队列,刚开始是只有一个的,然后不停往里面塞数字(注意,是有序的!从小到大最佳)如果不符题意,就重新开一个队列,最后我们的答案也就是所有队列长度中的最小值了。
代码:

#include <bits/stdc++.h>
using namespace std;

struct node
{
    long l;    //长度:length
    long b;      //队首:beginning
    long p;      //实力值:power
}x[100009];

long ans = 100009,a[100009];
int n;

int main()
{
    cin>>n;   //输入
    for (int i = 1; i <= n; i++)
        cin>>a[i];
    
    sort(a+1,a+n+1);     //排序
//对第一个队列进行预处理
    x[1].p = a[1];
    x[1].l = 1;
    x[1].b = 1; 
    for (int i = 2; i <= n; i++) 
        {
            if (a[i] == x[i-1].p + 1)    //判断可符题意
                {
                    x[i].l = x[i-1].l + 1;
                    x[i].p = a[i];
                    x[i].b = x[i-1].b;
                }
                else    //反之要重新开一个队列,进行操作
                    {
                    //	cout<<'q';
                        ans = min(ans,x[i-1].l);
                        x[i].b = i;
                        x[i].l = 1;
                        x[i].p = a[i];
                    }
        }
        
    cout<<min(ans,x[n].l);	   //输出
    
    return 0;
}

但是这样写,可否会有不足之处呢?才60分,肯定有!
我们可以再回顾一下,题面:
在这里插入图片描述
要求的是最少人数组的最大值?什么鬼东西mmp,理解一下,便是“使人数最少的组里面的人尽量多。”
就是是各组里面的人数尽量均衡——不是一定都要把所有能接上的值都给目前“最好的”,或者是最后一个队列,而是适当的分布,使实力值尽量均匀,每一组的人都在全局情况允许的情况下尽量最多。
来解决这个问题,我们便需要同时维护多个序列,但是按找上面那个垃圾做法,每一次维护,后半段都要发生改变的,超时不是梦想,肯定要超时呀,所以,对于每一个队列,我们都只维护一个元素,也就是队尾,因为来判断是否要相接的并不是前面的元素(前面的没鸟用),而是队尾的元素(翻身农奴把歌唱),只要用它就可以判断是否可以接上一个人。
维护多个队列的问题就解决了,但是下一个问题又来了,就是如何使每组的实力值均匀呢?如何“使得人数最少的组人数最多”呢?我们可以思考一下,每一次需要重新开队列,都是在前一个的下面的,而下面的未能接上只有2种可能:①是相等的;②太犇了;而上面的人数通常都是比下面的大的,下面的数都很“神奇”,所以我们就可以在每一次接的时候倒着来——更有可能能接上。
那下列的一组数据来说吧:
在这里插入图片描述
这样思路便是很清晰了,下面是代码:

#include <bits/stdc++.h>
using namespace std;

struct node
{
	long l;
	//long b;
	long p;
}x[100009];

long ans = 100009,a[100009];
int n,num;

int main()
{
	cin>>n;
	for (int i = 1; i <= n; i++)
		cin>>a[i];
	
	sort(a+1,a+n+1);    //排序

	x[1].p = a[1];   //预处理
	x[1].l = 1;
	num = 1;     //这个方法需要统计队列的个数,方便对多个队列进行维护
//	x[1].b = 1;      
	for (int i = 2; i <= n; i++) 
		{
			bool judge = true;      //判断是否需要新开队列
			
			for (int j = num; j >= 1; j--)      //同上面说的,倒着来
				{     //看能不能找到能接上的“最小的”
					if (x[j].p == a[i] - 1)   
						{
							x[j].p = a[i];
							x[j].l++;	
							judge = false;
							break;
						}
				}
		
			if (judge)      //接不上,另一种处理方式
				{	
					num++;
					x[num].l = 1;
					x[num].p = a[i];
				}
		}
	
	//for (int i = 1; i <= num; i++)
	//	cout<<x[i].p<<' '<<x[i].l<<endl;
	
	for (int i = 1; i <= num; i++)    //找“人数最少的人数最多的组”的人数
		{
			ans = min(ans,x[i].l);
			
		//	cout<<ans<<endl;
		}	
	
	cout<<ans;    //输出
	
	return 0;
}

T4:球球的排列
这题本来想写暴搜或用STL函数来枚举的,但是鬼畜的代码怎么都调不出来。。。QWQ。。。所以直接输出了n,后面。。。就没了吧。。。

AHOI2019加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值