• Glad You Came hdu-6356(ST表 || 线段树)


    第一种用线段树,用两颗数维护区间最大值和区间的最小值,然后更新的时候如果我目前区间内的最大值比我得到的v小,那么我就把这个区间修改成v,如果我的最小值比v大,那么v就是没有用的,直接跳过,然后这样每次更新[l, r]内的最大最小值,查询的时候返回每个位置的最大值,就可以求出答案

    线段树:

    #include<map>
    #include<set>
    #include<ctime>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lowbit(x) (x & (-x))
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    typedef unsigned int ui;
    const double pi = 4.0*atan(1.0);
    const int inf = 0x3f3f3f3f;
    const int maxn = 1e5;
    const int maxm = 2e5+10;
    const int mod = 1<<30;
    const double eps = 1e-8;
    using namespace std;
    
    int n, m;
    int T, tol;
    ui X, Y, Z;
    int mx[maxn << 2];
    int mn[maxn << 2];
    int lazy[maxn << 2];
    
    ui RNG61() {
        X = X ^ (X<<11);
        X = X ^ (X>>4);
        X = X ^ (X<<5);
        X = X ^ (X>>14);
        ll W = X ^ (Y ^ Z);
        X = Y;
        Y = Z;
        Z = W;
        return Z;
    }
    
    void init() {
        memset(mx, 0, sizeof mx);
        memset(mn, 0, sizeof mn);
        memset(lazy, 0, sizeof lazy);
    }
    
    void pushup(int root) {
        mx[root] = max(mx[root << 1], mx[root << 1 | 1]);
        mn[root] = min(mn[root << 1], mn[root << 1 | 1]);
    }
    
    void pushdown(int root) {
        if(lazy[root]) {
            mx[root << 1] = mx[root << 1 | 1] = lazy[root];
            mn[root << 1] = mn[root << 1 | 1] = lazy[root];
            lazy[root << 1] = lazy[root << 1 | 1] = lazy[root];
            lazy[root] = 0;
        }
    }
    
    void update(int left, int right, int prel, int prer, int val, int root) {
        if(prel <= left && right <= prer) {
            if(mx[root] < val) {
                mx[root] = mn[root] = val;
                lazy[root] = val;
                return ;
            }
            if(mn[root] > val)    return ;
        }
        if(mn[root] > val)    return ;
        pushdown(root);
        int mid = (left + right) >> 1;
        if(prel <= mid)    update(left, mid, prel, prer, val, root << 1);
        if(prer > mid)    update(mid+1, right, prel, prer, val, root << 1 | 1);
        pushup(root);
    }
    
    int query(int left, int right, int pos, int root) {
        if(left == right) {
            return mx[root];
        }
        pushdown(root);
        int mid = (left + right) >> 1;
        if(pos <= mid)    return query(left, mid, pos, root << 1);
        else            return query(mid+1, right, pos, root << 1 | 1);
    }
    
    int main() {
        scanf("%d", &T);
        while(T--) {
            scanf("%d%d%d%d%d", &n, &m, &X, &Y, &Z);
            init();
            for(int i=1; i<=m; i++) {
                ui f1 = RNG61();
                ui f2 = RNG61();
                ui f3 = RNG61();
                int l = min(f1%n+1, f2%n+1);
                int r = max(f1%n+1, f2%n+1);
                int v = f3 % mod;
                update(1, n, l, r, v, 1);
            }
            ll ans = 0;
            for(int i=1; i<=n; i++) {
                ans ^= (1ll * i * query(1, n, i, 1));
            }
            printf("%I64d
    ", ans);
        }
        return 0;
    }
    View Code

    原本的RMQ是得到每个位置的点值,然后一步一步更新成区间的最值,用

    st[i][j] = max(st[i][j-1],st[i+(1<<(j-1))][j-1])

    然后这里是先得到区间最值,然后往回更新到每个位置的点的最值,所以就是两个

    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])

    倒着更新

    然后题目里面数据很大,所以同样的log(r-l+1)/log(2.0)可能计算很多遍,可以把log(i)/log(2.0)打表出来,可以快一半的时间

    ST表:

    #include<map>
    #include<set>
    #include<ctime>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lowbit(x) (x & (-x))
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    typedef unsigned int ui;
    const double pi = 4.0*atan(1.0);
    const int inf = 0x3f3f3f3f;
    const int maxn = 1e5;
    const int maxm = 2e5+10;
    const int mod = 1<<30;
    const double eps = 1e-8;
    using namespace std;
    
    int n, m;
    int T, tol;
    ui X, Y, Z;
    
    int st[maxm][20];
    int lg[maxn];
    
    ui RNG61() {
        X = X ^ (X<<11);
        X = X ^ (X>>4);
        X = X ^ (X<<5);
        X = X ^ (X>>14);
        ll W = X ^ (Y ^ Z);
        X = Y;
        Y = Z;
        Z = W;
        return Z;
    }
    
    void init() {
        memset(st, 0, sizeof st);
    }
    
    void handle() {
        lg[0] = -1;
        for(int i=1; i<maxn; i++)    lg[i] = log(i) / log(2.0);
    }
    
    int main() {
        handle();
        scanf("%d", &T);
        while(T--) {
            scanf("%d%d%d%d%d", &n, &m, &X, &Y, &Z);
            init();
            for(int i=1; i<=m; i++) {
                ui f1 = RNG61();
                ui f2 = RNG61();
                ui f3 = RNG61();
                int l = min(f1%n+1, f2%n+1);
                int r = max(f1%n+1, f2%n+1);
                int v = f3 % mod;
                int k = lg[r-l+1];
                st[l][k] = max(st[l][k], v);
                st[r-(1<<k)+1][k] = max(st[r-(1<<k)+1][k], v);
            }
            int len = log(n) / log(2.0);
            for(int j=len; j>=1; j--) {
                for(int i=1; i<=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(int i=1; i<=n; i++)        ans = ans ^ (1ll * i * st[i][0]);
            printf("%I64d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    根据表生成接收(zml)
    删除指定日期,指定设备的排产记录(zml)
    1029 Median
    1027 Colors in Mars (20 分)进制转换
    1028 List Sorting 排序
    1025 PAT Ranking
    1024 Palindromic Number(大数加法)
    1023 Have Fun with Numbers
    1022 Digital Library
    逆序打印乘法表
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/9487655.html
Copyright © 2020-2023  润新知