zoukankan      html  css  js  c++  java
  • HDU 5737 Differencia set + 主席树

    HDU 5737

    很明显能发现数据是随机的。

    我们用set去维护值一样的段, 因为随机所以set里面线段的大小减少得很快, 平均大概30个左右。

    每次查询暴力处理每一段相同的在主席树上查找累加答案就可以了。

    但是这个好像不是标算, 标算复杂度(n + m) * log(n) 并且数据不是随机也可以。

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = (int)1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
    int n, m, A[N], B[N];
    
    struct Line {
        int l, r, val;
        bool operator < (const Line &rhs) const {
            return r < rhs.r;
        }
    };
    
    set<Line> S;
    
    int change(int L, int R, int val) {
        while(1) {
            auto it = S.lower_bound(Line{0, L, 0});
            if(it == S.end() || it->l > R) break;
            Line tmp = *it;
            S.erase(it);
            if(tmp.l < L) {
                S.insert(Line{tmp.l, L - 1, tmp.val});
            }
            if(tmp.r > R) {
                S.insert(Line{R + 1, tmp.r, tmp.val});
            }
        }
        S.insert(Line{L, R, val});
    }
    
    
    int Rt[N], hs[N], hs_cnt;
    struct ChairManTree {
        int tree_cnt;
        struct Node {
            int sum, ls, rs;
        } a[N * 20];
        void update(int p, int l, int r, int &x, int y) {
            x = ++tree_cnt;
            a[x] = a[y];
            a[x].sum++;
            if(l == r) return;
            int mid = l + r >> 1;
            if(p <= mid) update(p, l, mid, a[x].ls, a[y].ls);
            else update(p, mid + 1, r, a[x].rs, a[y].rs);
        }
        int query(int val, int l, int r, int x, int y) {
            if(hs[r] <= val) return a[x].sum - a[y].sum;
            if(hs[l] > val) return 0;
            int mid = l + r >> 1;
            return query(val, l, mid, a[x].ls, a[y].ls) + query(val, mid + 1, r, a[x].rs, a[y].rs);
        }
    } CT;
    
    int query(int L, int R) {
        int ql, qr, ans = 0;
        auto it = S.lower_bound(Line{0, L, 0});
        while(it != S.end() && it->l <= R) {
            ql = max(it->l, L);
            qr = min(it->r, R);
            ans += CT.query(it->val, 1, hs_cnt, Rt[qr], Rt[ql - 1]);
            ++it;
        }
        return ans;
    }
    
    int a, b, C = ~(1 << 31), M = (1 << 16) - 1;
    
    int rnd(int last) {
        a = (36969 + (last >> 3)) * (a & M) + (a >> 16);
        b = (18000 + (last >> 3)) * (b & M) + (b >> 16);
        return (C & ((a << 16) + b)) % 1000000000;
    }
    
    void init() {
        S.clear();
        CT.tree_cnt = 0;
        hs_cnt = 0;
    }
    
    int main() {
        int T; scanf("%d", &T);
        while(T--) {
            scanf("%d%d%d%d", &n, &m, &a, &b);
            init();
            for(int i = 1; i <= n; i++) {
                scanf("%d", &A[i]);
                S.insert(Line{i, i, A[i]});
            }
            for(int i = 1; i <= n; i++) {
                scanf("%d", &B[i]);
                hs[++hs_cnt] = B[i];
            }
            sort(hs + 1, hs + 1 + hs_cnt);
            hs_cnt = unique(hs + 1, hs + 1 + hs_cnt) - hs - 1;
            for(int i = 1; i <= n; i++) {
                B[i] = lower_bound(hs + 1, hs + 1 + hs_cnt, B[i]) - hs;
                CT.update(B[i], 1, hs_cnt, Rt[i], Rt[i - 1]);
            }
            int ans = 0;
            int last = 0, l, r, x;
            for(int i = 1; i <= m; i++) {
                l = rnd(last) % n + 1;
                r = rnd(last) % n + 1;
                if(l > r) swap(l, r);
                x = rnd(last) + 1;
                if((l + r + x) & 1) {
                    change(l, r, x);
                }
                else {
                    last = query(l, r);
                    add(ans, 1LL * i * last % mod);
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSIS 系列
    微软BI 之SSAS 系列
    微软BI 之SSRS 系列
    微软BI 之SSRS 系列
    配置 SQL Server Email 发送以及 Job 的 Notification通知功能
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11517511.html
Copyright © 2011-2022 走看看