麦哥

麦哥  •  14小时前


#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
#include <climits>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    
    // 前缀和
    vector<ll> prefix(n + 1, 0);
    for (int i = 1; i <= n; i++) {
        prefix[i] = prefix[i - 1] + a[i];
    }
    
    int q;
    cin >> q;
    
    while (q--) {
        int L, R;
        cin >> L >> R;
        
        vector<ll> k(n + 1, LLONG_MIN);
        
        // 单调队列:存储前缀和的下标,保持前缀和递增(用于求最小值)
        deque<int> dq_min;
        // 单调队列:存储前缀和的下标,保持前缀和递减(用于求最大值)
        deque<int> dq_max;
        
        // 第一部分:固定右端点 r,找最优左端点 l
        // 对于每个 r,l 的范围是 [max(1, r-R+1), r-L+1]
        // 我们要最大化 prefix[r] - prefix[l-1],即最小化 prefix[l-1]
        int left_bound = 0; // l-1 的范围是 [0, n]
        
        for (int r = 1; r <= n; r++) {
            // 维护 dq_min 为递增队列,队首是最小值
            int min_l = max(0, r - R);     // l-1 的最小值
            int max_l = r - L;             // l-1 的最大值
            
            if (max_l < 0) continue;
            
            // 将新的候选左端点加入队列
            while (left_bound <= max_l) {
                while (!dq_min.empty() && prefix[dq_min.back()] >= prefix[left_bound]) {
                    dq_min.pop_back();
                }
                dq_min.push_back(left_bound);
                left_bound++;
            }
            
            // 移除超出范围的左端点
            while (!dq_min.empty() && dq_min.front() < min_l) {
                dq_min.pop_front();
            }
            
            if (!dq_min.empty()) {
                ll min_prefix = prefix[dq_min.front()];
                ll sum = prefix[r] - min_prefix;
                // 这个区间 [l, r] 包含所有 i ∈ [l, r]
                int l = dq_min.front() + 1;
                for (int i = l; i <= r; i++) {
                    k[i] = max(k[i], sum);
                }
            }
        }
        
        // 第二部分:固定左端点 l,找最优右端点 r
        // 对于每个 l,r 的范围是 [l+L-1, min(n, l+R-1)]
        // 我们要最大化 prefix[r] - prefix[l-1],即最大化 prefix[r]
        int right_bound = 1;
        
        for (int l = 1; l <= n; l++) {
            int min_r = l + L - 1;
            int max_r = min(n, l + R - 1);
            
            if (min_r > n) continue;
            
            // 将新的候选右端点加入队列
            while (right_bound <= max_r) {
                while (!dq_max.empty() && prefix[dq_max.back()] <= prefix[right_bound]) {
                    dq_max.pop_back();
                }
                dq_max.push_back(right_bound);
                right_bound++;
            }
            
            // 移除超出范围的右端点
            while (!dq_max.empty() && dq_max.front() < min_r) {
                dq_max.pop_front();
            }
            
            if (!dq_max.empty()) {
                ll max_prefix = prefix[dq_max.front()];
                ll sum = max_prefix - prefix[l - 1];
                // 这个区间 [l, r] 包含所有 i ∈ [l, r]
                int r = dq_max.front();
                for (int i = l; i <= r; i++) {
                    k[i] = max(k[i], sum);
                }
            }
        }
        
        // 处理单点区间(长度为1)
        for (int i = 1; i <= n; i++) {
            if (L <= 1 && 1 <= R) {
                k[i] = max(k[i], a[i]);
            }
        }
        
        // 计算答案
        ull ans = 0;
        for (int i = 1; i <= n; i++) {
            if (k[i] == LLONG_MIN) {
                // 如果没有符合条件的区间,权值为0
                k[i] = 0;
            }
            ull term = (ull)i * (ull)max(0LL, k[i]); // 非负处理
            ans ^= term;
        }
        
        cout << ans << "\n";
    }
    
    return 0;
}

include

include

include

include

include

using namespace std;

typedef long long ll; typedef unsigned long long ull;

int main() {

ios::sync_with_stdio(false);
cin.tie(nullptr);

int n;
cin >> n;
vector<ll> a(n + 1);
for (int i = 1; i <= n; i++) {
    cin >> a[i];
}

// 前缀和
vector<ll> prefix(n + 1, 0);
for (int i = 1; i <= n; i++) {
    prefix[i] = prefix[i - 1] + a[i];
}

int q;
cin >> q;

while (q--) {
    int L, R;
    cin >> L >> R;
    
    vector<ll> k(n + 1, LLONG_MIN);
    
    // 单调队列:存储前缀和的下标,保持前缀和递增(用于求最小值)
    deque<int> dq_min;
    // 单调队列:存储前缀和的下标,保持前缀和递减(用于求最大值)
    deque<int> dq_max;
    
    // 第一部分:固定右端点 r,找最优左端点 l
    // 对于每个 r,l 的范围是 [max(1, r-R+1), r-L+1]
    // 我们要最大化 prefix[r] - prefix[l-1],即最小化 prefix[l-1]
    int left_bound = 0; // l-1 的范围是 [0, n]
    
    for (int r = 1; r <= n; r++) {
        // 维护 dq_min 为递增队列,队首是最小值
        int min_l = max(0, r - R);     // l-1 的最小值
        int max_l = r - L;             // l-1 的最大值
        
        if (max_l < 0) continue;
        
        // 将新的候选左端点加入队列
        while (left_bound <= max_l) {
            while (!dq_min.empty() && prefix[dq_min.back()] >= prefix[left_bound]) {
                dq_min.pop_back();
            }
            dq_min.push_back(left_bound);
            left_bound++;
        }
        
        // 移除超出范围的左端点
        while (!dq_min.empty() && dq_min.front() < min_l) {
            dq_min.pop_front();
        }
        
        if (!dq_min.empty()) {
            ll min_prefix = prefix[dq_min.front()];
            ll sum = prefix[r] - min_prefix;
            // 这个区间 [l, r] 包含所有 i ∈ [l, r]
            int l = dq_min.front() + 1;
            for (int i = l; i <= r; i++) {
                k[i] = max(k[i], sum);
            }
        }
    }
    
    // 第二部分:固定左端点 l,找最优右端点 r
    // 对于每个 l,r 的范围是 [l+L-1, min(n, l+R-1)]
    // 我们要最大化 prefix[r] - prefix[l-1],即最大化 prefix[r]
    int right_bound = 1;
    
    for (int l = 1; l <= n; l++) {
        int min_r = l + L - 1;
        int max_r = min(n, l + R - 1);
        
        if (min_r > n) continue;
        
        // 将新的候选右端点加入队列
        while (right_bound <= max_r) {
            while (!dq_max.empty() && prefix[dq_max.back()] <= prefix[right_bound]) {
                dq_max.pop_back();
            }
            dq_max.push_back(right_bound);
            right_bound++;
        }
        
        // 移除超出范围的右端点
        while (!dq_max.empty() && dq_max.front() < min_r) {
            dq_max.pop_front();
        }
        
        if (!dq_max.empty()) {
            ll max_prefix = prefix[dq_max.front()];
            ll sum = max_prefix - prefix[l - 1];
            // 这个区间 [l, r] 包含所有 i ∈ [l, r]
            int r = dq_max.front();
            for (int i = l; i <= r; i++) {
                k[i] = max(k[i], sum);
            }
        }
    }
    
    // 处理单点区间(长度为1)
    for (int i = 1; i <= n; i++) {
        if (L <= 1 && 1 <= R) {
            k[i] = max(k[i], a[i]);
        }
    }
    
    // 计算答案
    ull ans = 0;
    for (int i = 1; i <= n; i++) {
        if (k[i] == LLONG_MIN) {
            // 如果没有符合条件的区间,权值为0
            k[i] = 0;
        }
        ull term = (ull)i * (ull)max(0LL, k[i]); // 非负处理
        ans ^= term;
    }
    
    cout << ans << "\n";
}

return 0;

}



评论:

请先登录,才能进行评论