hdu6356 Glad You Came 杭电多校第五场 RMQ ST表(模板)

Glad You Came

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1489    Accepted Submission(s): 629


Problem Description
Steve has an integer array  a of length n (1-based). He assigned all the elements as zero at the beginning. After that, he made m operations, each of which is to update an interval of a with some value. You need to figure out ni=1(iai) after all his operations are finished, where  means the bitwise exclusive-OR operator.
In order to avoid huge input data, these operations are encrypted through some particular approach.
There are three unsigned 32-bit integers X,Y and Z which have initial values given by the input. A random number generator function is described as following, where  means the bitwise exclusive-OR operator, << means the bitwise left shift operator and >> means the bitwise right shift operator. Note that function would change the values of X,Y and Z after calling.

Let the i-th result value of calling the above function as fi (i=1,2,,3m). The i-th operation of Steve is to update aj as vi if aj<vi (j=li,li+1,,ri), where
⎧⎩⎨⎪⎪lirivi=min((f3i2modn)+1,(f3i1modn)+1)=max((f3i2modn)+1,(f3i1modn)+1)=f3imod230(i=1,2,,m).
 

 

Input
The first line contains one integer  T, indicating the number of test cases.
Each of the following T lines describes a test case and contains five space-separated integers n,m,X,Y and Z.
1T1001n1051m51060X,Y,Z<230.
It is guaranteed that the sum of n in all the test cases does not exceed 106 and the sum of m in all the test cases does not exceed 5107.
 

 

Output
For each test case, output the answer in one line.
 

 

Sample Input
4 1 10 100 1000 10000 10 100 1000 10000 100000 100 1000 10000 100000 1000000 1000 10000 100000 1000000 10000000
 

 

Sample Output
1031463378 1446334207 351511856 47320301347
Hint
In the first sample, a = [1031463378] after all the operations. In the second sample, a = [1036205629, 1064909195, 1044643689, 1062944339, 1062944339, 1062944339, 1062944339, 1057472915, 1057472915, 1030626924] after all the operations.
 

 

Source
 
 
首先用ST表维护区间最大值,st[i][j]维护的是i以后2^j个数的最大值
然后反向求一遍ST表可以求出每个数的最大值,此时st[i][0]就是每个数的最大值
再按照题目意思求每个值与其位置的乘积再异或一遍
贴一份讲解RMQ-ST表的博客:https://www.cnblogs.com/l609929321/p/9439145.html
AC代码:
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <string>
#include <bitset>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define ls (r<<1)
#define rs (r<<1|1)
#define debug(a) cout << #a << " " << a << endl
using namespace std;
typedef long long ll;
const ll maxn = 1e5+10;
const ll mod = 998244353;
const double pi = acos(-1.0);
const double eps = 1e-8;
unsigned x, y, z;
unsigned rng() {
    x ^= x << 11;
    x ^= x >> 4;
    x ^= x << 5;
    x ^= x >> 14;
    unsigned w = x^(y^z);
    x = y;
    y = z;
    z = w;
    return z;
}
ll n, m, a[maxn], st[maxn][20], Log[maxn];
void update( ll le, ll ri, ll z ) { //维护(le,ri)区间最大值
    ll k = Log[ri-le+1];
    st[le][k] = max(st[le][k],z);
    st[ri-(1<<k)+1][k] = max(st[ri-(1<<k)+1][k],z);
}

int main() {
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    Log[2] = 1;
    for( ll i = 3; i < maxn; i ++ ) {  //预处理区间所有log2()的值,节省时间
        Log[i] = Log[i>>1]+1;
    }
    ll T;
    cin >> T;
    while( T -- ) {
        cin >> n >> m >> x >> y >> z;
        for( ll i = 1; i <= n; i ++ ) {  //n最大的情况下,log2(maxn) = 16
            for( ll j = 0; j < 18; j ++ ) {
                st[i][j] = 0;
            }
        }
        for( ll i = 1; i <= m; i ++ ) {
            ll x = rng()%n+1, y = rng()%n+1, z = rng()%(1<<30);
            update(min(x,y),max(x,y),z);
        }
        for( ll j = 17; j; j -- ) {  //反向一遍st求出每一个数的最大值
            for( ll i = 1; i+(1<<j)-1 <= n; i ++ ) {
                st[i][j-1] = max(st[i][j-1],st[i][j]);
                st[i+(1<<(j-1))][j-1] = max(st[i+(1<<(j-1))][j-1],st[i][j]);
            }
        }
        ll ans = 0;
        for( ll i = 1; i <= n; i ++ ) {
            ans = ans^(i*st[i][0]);
        }
        cout << ans << endl;
    }
    return 0;
}

  

  

 

转载于:https://www.cnblogs.com/l609929321/p/9437505.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值