洛谷 - B3666 求数列所有后缀最大值的位置 题解

3 篇文章 0 订阅

B3666 求数列所有后缀最大值的位置 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题意:

        题目的要求是(ai > aj ,i  < j  < |a| ),也就是说从后往前看(从后往前遍历),这个元素是当前数列的最大值的话,就将下标异或,每输入一个x,就输出一个结果

题解:

        如果每一次都要从后往前遍历会特别浪费时间,不妨找一下规律,会发现只有形成单调递减的数列,才会异或所有下标,由此我们能想到单调栈,中间那些不能形成单调递减的元素,已经没有用处了,我们就可以把他pop掉。

        整理以上思路,该题就是要,每加入一次x,就异或一次(因为x是最后一个,一定是后缀最大值元素),然后构建一个单调栈(存下标的),如果有元素大于栈顶下标的元素,将弹出的下标再异或一次(利用两个相同的数异或等于0的性质,我们可以把该下标处理掉),接着输出每一步的异或和。

        同时还要注意,该题的ai的范围是0~2^64,大于long long范围,而且我们知道异或不会异或出负数,所以需要用到unsigned long long

代码如下:
#include<bits/stdc++.h>
#define int unsigned long long
#define endl '\n'
using namespace std;
int a[1000010];
void sl()
{
	stack<int> st;
	int n , ans = 0, last = 0;
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		cin >> a[i];
		while(!st.empty() && a[i] > a[st.top()]) // 构建单调栈,有不单调的就pop
		{
			last ^= st.top(); // 处理掉没有用的下标
			st.pop();
		}
		last ^= i;
		ans = last; // last即为答案
		st.push(i);
		cout << ans << endl;
	}
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	
	int T;
	T = 1;
	while(T--) sl();
	return 0;
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值