zoukankan      html  css  js  c++  java
  • 2019 Multi-University Training Contest 10

    分治 + ST表

    先预处理出区间内最大值的位置和每个数向左和向右能够延伸的最大距离。

    然后把每个区间的最大值的位置当成中点来分治统计每个数的贡献。

    统计的时候选区间较短的统计,类似于启发式合并?

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    #define __fastIn ios::sync_with_stdio(false), cin.tie(0)
    #define pb push_back
    using namespace std;
    using LL = long long;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int ret = 0, w = 0; char ch = 0;
        while(!isdigit(ch)){
            w |= ch == '-', ch = getchar();
        }
        while(isdigit(ch)){
            ret = (ret << 3) + (ret << 1) + (ch ^ 48);
            ch = getchar();
        }
        return w ? -ret : ret;
    }
    template <typename A>
    inline A __lcm(A a, A b){ return a / __gcd(a, b) * b; }
    template <typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 300005;
    int _, n, k, a[N], L[N], R[N], pos[N], lb[N], st[N][25];
    LL ans;
    
    void initST(){
        for(int i = 1; i <= n; i ++) st[i][0] = i;
        for(int j = 1; j <= 20; j ++){
            for(int i = 1; i + (1 << j) - 1 <= n; i ++){
                int p = st[i][j - 1], q = st[i + (1 << (j - 1))][j - 1];
                st[i][j] = a[p] > a[q] ?  p : q;
            }
        }
    }
    
    int query(int l, int r){
        int t = lb[r - l + 1];
        int p = st[l][t], q = st[r - (1 << t) + 1][t];
        return a[p] > a[q] ? p : q;
    }
    
    void solve(int l, int r){
        if(l > r) return;
        int mid = query(l, r);
        solve(l, mid - 1), solve(mid + 1, r);
    
        int x = a[mid] - k;
        if(mid - l < r - mid){
            for(int i = l; i <= mid; i ++){
                int lower = max(i + x - 1, mid);
                int upper = min(R[i], r);
                if(upper >= lower) ans += upper - lower + 1;
            }
        }
        else{
            for(int i = mid; i <= r; i ++){
                int lower = min(i - x + 1, mid);
                int upper = max(L[i], l);
                if(upper <= lower) ans += lower - upper + 1;
            }
        }
    }
    
    int main(){
    
        lb[0] = -1; for(int i = 1; i < N; i ++) lb[i] = lb[i >> 1] + 1;
        for(_ = read(); _; _ --){
            ans = 0;
            n = read(), k = read();
            for(int i = 1; i <= n; i ++) a[i] = read();
            for(int i = 1; i <= n; i ++) pos[i] = 0;
            for(int i = 1; i <= n; i ++){
                L[i] = pos[a[i]] + 1;
                pos[a[i]] = i;
            }
            for(int i = 2; i <= n; i ++){
                L[i] = max(L[i - 1], L[i]);
            }
            for(int i = 1; i <= n; i ++) pos[i] = n + 1;
            for(int i = n; i >= 1; i --){
                R[i] = pos[a[i]] - 1;
                pos[a[i]] = i;
            }
            for(int i = n - 1; i >= 1; i --){
                R[i] = min(R[i + 1], R[i]);
            }
            initST();
            solve(1, n);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    update set from 语句用法
    SQL WITH AS用法
    SQL插入数据的多种方式
    本地临时表“#” 与 全局临时表 "##"
    sql常用语句
    关于mybatis转义SQL动态执行语句变慢的原因
    关于SQL中OUTER APPLY 得用法
    AspNetPager控件的简单使用
    JQuery常用的案例
    JQuery的学习笔记
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/11396759.html
Copyright © 2011-2022 走看看