hdu6358 Glad You Came

题意:首先一个长度为n的a数组,全为0。一个长度为3m的b数组,通过题目给的随机生成,然后根据题目给出的公式,区间【l,r】和一个数v对于区间内的数a【i】=max(a【i】,v),计算出a[i]的每个值,然后求与i的异或和。
正解是用反向RMQ,更新每段区间,然后压到每一项上。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn =1e5+10;
int mm[maxn*5];
int f[20][maxn*5];
unsigned X,Y,Z;
unsigned RNG61()
{
    X=X^(X<<11);
    X=X^(X>>4);
    X=X^(X<<5);
    X=X^(X>>14);
    unsigned W=X^(Y^Z);
    X=Y;
    Y=Z;
    Z=W;
    return Z;
}
void update(int l,int r,int v)
{
    int k=mm[r-l+1];
    f[k][l]=max(f[k][l],v);
    f[k][r-(1<<k)+1]=max(f[k][r-(1<<k)+1],v);
}
int main()
{
    mm[2] = 1;
    for(int i = 3; i < maxn; i++)
        mm[i] = mm[i >> 1] + 1;
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int n, m;
        cin>>n>>m>>X>>Y>>Z;
        for(int j=0;j<20;j++)
        {
            for(int i=1;i<=n;i++)
            {
                f[j][i]=0;
            }
        }
        for(int i = 1; i <= m; i++) 
        {
            int x=RNG61()%n+1,y=RNG61()%n+1,z=RNG61()%(1<<30);
            update(min(x,y),max(x,y),z);
        }
        for(int i=19;i>=1;i--)
        {
            for(int j=1;j+(1<<i)-1<=n;j++)
            {
                f[i-1][j]=max(f[i-1][j],f[i][j]);
                f[i-1][j+(1<<i-1)]=max(f[i-1][j+(1<<i-1)],f[i][j]);
            }
        }
        long long ans=0;
        for(int i=1;i<=n;i++)
        {
            ans=ans^(i*(long long)f[0][i]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值