题解:BISHI121 数列后缀极大位置统计

题目链接

数列后缀极大位置统计

题目描述

初始数列为空,依次在末尾追加 个正整数。每次追加后,设当前长度为 ,若下标 满足对所有 均有 ,则称 为“后缀极大”的位置。请在每次操作后输出所有“后缀极大”下标的按位异或值。

解题思路

维护一个“后缀极大位置”的单调栈(下标递增,值非降)。当在位置 追加值

  • 不断弹出所有值 的栈顶位置(它们不再是后缀极大),同时把这些下标从答案按位异或中移除;
  • 将新位置 入栈,并把 与答案按位异或;
  • 注意当 与栈顶值相等时,旧位置仍是后缀极大(允许相等),不弹出。

每个下标最多进栈出栈一次,总复杂度

代码

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

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int q; if (!(cin >> q)) return 0;
    vector<pair<int,long long>> st; st.reserve(q); // (index, value)
    int ans = 0;
    for (int i = 1; i <= q; ++i) {
        long long x; cin >> x;
        while (!st.empty() && st.back().second < x) {
            ans ^= st.back().first;
            st.pop_back();
        }
        st.emplace_back(i, x);
        ans ^= i;
        cout << ans << '\n';
    }
    return 0;
}
import java.io.*;

public class Main {
    static class FastScanner {
        private final InputStream in; private final byte[] buf = new byte[1<<16];
        private int p=0,l=0; FastScanner(InputStream is){in=is;}
        private int read() throws IOException { if(p>=l){ l=in.read(buf); p=0; if(l<=0) return -1; } return buf[p++]; }
        int nextInt() throws IOException { int c; int s=1,x=0; do{c=read();}while(c<=32); if(c=='-'){s=-1;c=read();} while(c>32){ x=x*10+(c-'0'); c=read(); } return x*s; }
        long nextLong() throws IOException { int c; long s=1,x=0; do{c=read();}while(c<=32); if(c=='-'){s=-1;c=read();} while(c>32){ x=x*10+(c-'0'); c=read(); } return x*s; }
    }

    public static void main(String[] args) throws Exception {
        FastScanner fs = new FastScanner(System.in);
        int q = fs.nextInt();
        int[] idx = new int[q];
        long[] val = new long[q];
        int top = 0; // stack size
        int ans = 0;
        for (int i = 1; i <= q; i++) {
            long x = fs.nextLong();
            while (top > 0 && val[top-1] < x) {
                ans ^= idx[top-1];
                top--;
            }
            idx[top] = i; val[top] = x; top++;
            ans ^= i;
            System.out.println(ans);
        }
    }
}
import sys

data = sys.stdin.buffer.read().split()
it = iter(data)
q = int(next(it))

stack_idx = [0]*q
stack_val = [0]*q
top = 0
ans = 0

out_lines = []
for i in range(1, q+1):
    x = int(next(it))
    while top > 0 and stack_val[top-1] < x:
        ans ^= stack_idx[top-1]
        top -= 1
    stack_idx[top] = i
    stack_val[top] = x
    top += 1
    ans ^= i
    out_lines.append(str(ans))

sys.stdout.write('\n'.join(out_lines))

算法及复杂度

  • 算法:单调栈(值非降)维护后缀极大位置,异或值增量更新
  • 时间复杂度:
  • 空间复杂度: