HDU 6356 Glad You Came【线段树lazy】

题意: (a,b) ( a , b ) 区间内的数 = max((a,b),val) m a x ( ( a , b ) , v a l ) ,初始为0,最后只有一次查询.
分析:
线段树维护区间最小值,lazy进行区间操作,要有个减枝过程:就是减掉区间 (a,b)min>=val ( a , b ) m i n >= v a l 的状态.
这里写图片描述

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = a; i <= b; ++i)

typedef long long LL;
const int MAXN = 4e5 + 10;
LL lazy[MAXN], dp[MAXN];
unsigned int a[MAXN * 40];

unsigned int f(unsigned int &x, unsigned int &y, unsigned int &z){
    x = x ^ (x << 11);
    x = x ^ (x >> 4);
    x = x ^ (x << 5);
    x = x ^ (x >> 14);
    unsigned int w = x ^ (y ^ z);
    x = y;
    y = z;
    z = w;
    return z;
}

inline void up(int rt) {
    dp[rt] = min(dp[rt << 1], dp[rt << 1 | 1]);
}

inline void down(int rt) {
    lazy[rt << 1] = max(lazy[rt << 1], lazy[rt]);
    lazy[rt << 1 | 1] = max(lazy[rt << 1 | 1], lazy[rt]);
    dp[rt << 1] = max(dp[rt << 1], lazy[rt]);
    dp[rt << 1 | 1] = max(dp[rt << 1 | 1], lazy[rt]);
}

inline void update(int rt, int L, int R, int l ,int r, unsigned int val) {
    if(dp[rt] >= val || lazy[rt] >= val) return ;//减枝
    if(l <= L && R <= r) {
        lazy[rt] = max(1ll * val, lazy[rt]);
        dp[rt] = max(1ll * val, dp[rt]);
        return ;
    }
    down(rt);
    int mid = (L + R) >> 1;
    if(l <= mid) update(rt << 1, L, mid, l, r, val);
    if(r > mid) update(rt << 1 | 1, mid + 1, R, l, r, val);
    up(rt);
}

inline LL query(int rt, int L, int R, int l, int r) {
    if(L == R) {
        return dp[rt] * 1ll * L;
    }
    down(rt); LL ans = 0;
    int mid = (L + R) >> 1;
    if(l <= mid) ans ^= query(rt << 1, L, mid, l, r);
    if(r > mid) ans ^= query(rt << 1 | 1, mid + 1, R, l, r); 
    return ans;
}

int main() {
    int T, n, m;
    unsigned int x, y, z;
    scanf("%d", &T);
    while(T--) {
        memset(dp, 0, sizeof(dp));
        memset(lazy, 0, sizeof(lazy));
        cin >> n >> m >> x >> y >> z;
        rep(i, 1, 3 * m) a[i] = f(x, y, z);
        rep(i, 1, m) {
            int le = min(a[3 * i - 2] % n + 1, a[3 * i  - 1] % n + 1);
            int ri = max(a[3 * i - 2] % n + 1, a[3 * i  - 1] % n + 1);
            unsigned int v = a[3 * i] % (1 << 30);
            update(1, 1, n, le, ri, v);
        }
        LL ans = query(1, 1, n, 1, n);
        printf("%lld\n", ans);
    }
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值