牛客OI周赛7---B:小睿睿的询问(ST表)

题目:

小睿睿的n个妹纸排成一排,每个妹纸有一个颜值val[i]。有m个询问,对于每一个询问,小睿睿想知道区间[L,R]颜值最高而编号最小的妹纸是哪一个

分析:

题意只求区间最大值的下标,O(n*logn+m*logn)的线段树肯定会T,没有修改操作,首先选择O(nlogn+m)的ST表;考虑在初始化DP[i][j]时,同时dp[i][j]记录DP[i][j]的值来自那里

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 1e5+15;
int DP[maxn][20],arr[maxn],dp[maxn][20];
void init(int n)
{
    for(int i=1;i<=n;i++){
        DP[i][0]=arr[i];
        dp[i][0] = i;
    }
    for(int j=1; (1<<j)<=n; ++j){
       for(int i=1; i+(1<<j)-1<=n; ++i){
        if(DP[i][j-1] >= DP[i+(1<<(j-1))][j-1]){
            DP[i][j] = DP[i][j-1];
            dp[i][j] = dp[i][j-1];
        }else{
            DP[i][j] = DP[i+(1<<(j-1))][j-1];
            dp[i][j] = dp[i+(1<<(j-1))][j-1];
        }
       }
    }
}
inline int result(int l,int r)
{
    int k=trunc(log2(r*1.0-l+1));
    return DP[l][k] >= DP[r-(1<<k)+1][k] ? dp[l][k] : dp[r-(1<<k)+1][k];
}
void generate_array(int n,int seed)
{
    unsigned x = seed;
    for (int i=1;i<=n;++i)
    {
        x ^= x << 13;
        x ^= x >> 17;
        x ^= x << 5;
        arr[i] = x % 100;
    }
}
int generate_ask(int n,int m,int seedx,int seedy)
{
    int res = 0,lastans=0;
    unsigned x = seedx,y = seedy;
    for (int i=1;i<=m;++i)
    {
        x ^= x << 13;
        x ^= x >> 17;
        x ^= x << 5;
        y ^= y << 13;
        y ^= y >> 17;
        y ^= y << 5;
        int L=(x^lastans)%n+1,R=(y^lastans)%n+1;
        if (L>R) swap(L,R);
        lastans = result(L,R);
        res ^= lastans;
    }
    return res;
}
int main()
{
    int n,m,seedx,seedy,seed;
    cin>>n>>m>>seed>>seedx>>seedy;
    generate_array(n,seed);
    init(n);
    cout<<generate_ask(n,m,seedx,seedy)<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41157137/article/details/87887327