位位运算 方法记录

科技资讯 投稿 24700 0 评论

位位运算 方法记录

题解

手里的数:即我们输入的长度为\(n\的序列;

手上的数 的 最大子段和

小朋友特征值和分数的和 的最大值(第一个小朋友的分数等于其特征值)。

一、求每个小朋友对应的最大子段和

最大子段和模板题

最大子段和的核心思想

2.如果 一个数加上上一个有效子段 的结果 大于 这个数,那么  这个数属于上一个有效子段。

一个数加上上一个有效子段 的结果 小于 这个数,那么  这个数成为一个新的有效子段。

	for(int i=1;i<=n;i++
	{
		scanf("%lld",&hand;//hand是输入的手里的数 
		if(i==1 tmp[i]=hand;//tmp[]记录子段 
		else tmp[i]=maxx(hand,tmp[i-1]+hand;//取hand是第3种情况,取tmp[i-1]+hand是第2种情况 
		sub=maxx(sub,tmp[i];//sub是第i个小朋友对应的最大子段和(特征值) 
		stu[i].spl=sub;
	}
注意
sub=maxx(sub,tmp[i];
stu[i].spl=sub;
不能写成
stu[i].spl=maxx(stu[i].spl,tmp[i];
因为\(sub\后续还会用到,所以需要持久地保存下来。

二、线性统计所有小朋友分数的最大值

第一个小朋友的分数就是其特征值。

……

\(x\,那么下一个小朋友的分数就是 \(x\、下一个小朋友与\(x\的和 的最大值。、

stu[1].sco=stu[1].spl;
	x=stu[1].sco+stu[1].spl;
	ans=stu[1].sco;
	for(int i=2;i<=n;i++
	{
		stu[i].sco=x;
		x=maxx(x,stu[i].spl+stu[i].sco;
		ans=maxx(ans,stu[i].sco;
	}

考虑到数据范围导致运算时会出现超过\(long long\的值,所以可以使用__128来声明参与运算的变量,注意输入输出不能用__128。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const __int128 N=1000005;
const __int128 inf=2147483647;
ll n,p,hand;
__int128 x,ans;
struct student
{
	__int128 spl,sco;
}stu[N];
__int128 tmp[N];
__int128 maxx(__int128 a,__int128 b
{
	return a>b?a:b;
}
__int128 sub=-inf;
ll final;
signed main(
{
	//freopen("number.in","r",stdin;
	//freopen("number.out","w",stdout;
	scanf("%lld%lld",&n,&p;
	for(int i=1;i<=n;i++
	{
		scanf("%lld",&hand;//hand是输入的手里的数 
		if(i==1 tmp[i]=hand;//tmp[]记录子段 
		else tmp[i]=maxx(hand,tmp[i-1]+hand;//取hand是第3种情况,取tmp[i-1]+hand是第2种情况 
		sub=maxx(sub,tmp[i];//sub是第i个小朋友对应的最大子段和(特征值) 
		stu[i].spl=sub;
	}
	stu[1].sco=stu[1].spl;
	x=stu[1].sco+stu[1].spl;
	ans=stu[1].sco;
	for(int i=2;i<=n;i++
	{
		stu[i].sco=x;
		x=maxx(x,stu[i].spl+stu[i].sco;
		ans=maxx(ans,stu[i].sco;
	}
	if(ans>=0
	{
		ans=ans%p;
		final=ans;
		printf("%lld",final;
	}
	else
	{
		ans=-ans;
		ans=ans%p;
		final=ans;
		printf("-%lld",final;
	}
	return 0;
}

编程笔记 » 位位运算 方法记录

赞同 (24) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽