2018 ACM-ICPC 宁夏邀请赛 A. Maximum Element In A Stack(思路题)

链接:Maximum Element In A Stack

题意:让维护一个栈,每次操作之后询问栈里的最大值xi,求(1*x1)^(2*x2)^……^(n*xn)的结果。

思路分析:首先暴力每次入栈找最大值肯定T,现场赛时我们队想到的思路是维护一个stack和一个multiset(或者map),每次push最大值是m.end()-1对应的值,pop的话,在stack里找到top,然后在multiset里find值对应的迭代器erase。抱着侥幸态度WA了10多发,卡了我们一个半小时,这个全场题导致最后我们与银牌无缘。后来反思,这是一道思路题,正确的做法是每次push时将将入栈元素与栈顶元素cmp一下,push大的值,而pop的时候直接pop栈顶元素,由于堆栈先入后出的特性,较小元素在较大元素之后加入stack不会影响每次操作后所求的最大值,最大值永远不可能是后加入的较小元素,所以它具体是多少就变得无关紧要了,那么就可以把它改成最大值,这样的话无论怎样操作,总能保证栈顶元素 = 栈内最大值。即使清楚了思路,今天网络赛仍然WA了三次,这个题爆int,原因是i与xi相乘时可能超出int范围。

AC代码:

#include <bits/stdc++.h>
using namespace std;
int n,p,q,m;
unsigned int SA,SB,SC;
stack<long long>s;
void PUSH(long long x){
	if(s.empty())s.push(x);
	else s.push(max(x,s.top()));
}
void POP(){
	if(!s.empty())
	s.pop();
}
unsigned int rng61(){
	SA ^= SA << 16;
	SA ^= SA >> 5;
	SA ^= SA << 1;
	unsigned int t = SA;
	SA = SB;
	SB = SC;
	SC ^= t ^ SA;
	return SC;
}
int main(){
	int T;
	scanf("%d",&T);
	for(int t = 1;t <= T;t++){
		while(!s.empty())s.pop();
		long long ans = 0;
		scanf("%d%d%d%d%u%u%u",&n,&p,&q,&m,&SA,&SB,&SC);
		for(int i = 1;i <= n;i++){
			if(rng61() % (p + q) < p)PUSH(rng61() % m + 1);
			else POP();
			if(!s.empty())ans ^= (i*s.top());
		}
		printf("Case #%d: %lld\n",t,ans);
	}
	return 0;
}

标程:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=5000005;
int stk[MAXN],top,res[MAXN];
int n, p, q, m;
unsigned int SA,SB,SC;
unsigned int rng61()
{
    SA ^= SA << 16;
    SA ^= SA >> 5;
    SA ^= SA << 1;
    unsigned int t = SA;
    SA = SB;
    SB = SC;
    SC ^= t ^ SA;
    return SC;
}
long long solve()
{
    scanf("%d%d%d%d%u%u%u",&n,&p,&q,&m,&SA,&SB,&SC);
    long long res=(top=0);
    for(int i=1;i<=n;i++)
    {
        if(rng61()%(p+q)<p)
        {
            ++top;
            stk[top]=rng61()%m+1;
            stk[top]=max(stk[top],stk[top-1]);
        }
        else top=max(top-1,0);
        res^=1LL*i*stk[top];
    }
    return res;
}
int main()
{
    int T;
    scanf("%d",&T);
    for(int ca=1; ca<=T; ca++)
        printf("Case #%d: %lld\n",ca,solve());
    return 0;
}

相关链接:

Tracking current Maximum Element in a Stack - GeeksforGeeks

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM-ICPC(国际大学生程序设计竞赛)是一项面向大学生的计算机编程竞赛,涉及算法和数据结构等领域。在比赛中,选手需要解决一系列编程问,使用合适的算法和数据结构来实现正确和高效的解决方案。 对于整理ACM-ICPC模板,以下是一些建议: 1. 了解比赛要求:首先,你需要了解ACM-ICPC比赛的具体要求和规则。这包括了解比赛所涉及的算法和数据结构,以及目的类型和难度等。 2. 收集资料:收集与ACM-ICPC相关的资料,包括经典算法和数据结构的实现代码、常见问的解思路等。可以参考教材、博客、论文等资源。 3. 整理模板:将收集到的资料整理成模板。可以按照算法和数据结构的分类进行整理,例如排序算法、图算法、字符串算法等。对每个模板,添加必要的注释和示例代码,以便理解和使用。 4. 测试代码:对每个模板编写测试代码,确保它们的正确性和可靠性。可以使用已知的测试用例或自行设计测试用例。 5. 更新与扩充:定期更新和扩充模板,以适应ACM-ICPC比赛中新出现的算法和数据结构。同时,根据自己的经验和理解,对模板进行优化和改进。 6. 练习和复习:在比赛之前,利用整理好的模板进行练习和复习。尝试解决一些经典问,使用模板中的算法和数据结构进行实现,并进行优化。 希望这些建议对你整理ACM-ICPC模板有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值