zoukankan      html  css  js  c++  java
  • [2019杭电多校第十场][hdu6701]Make Rounddog Happy

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6701

    题目大意为求满足 $max(a_{l},a_{l+1}cdot cdot cdot a_{r})-(r-l+1)<=k$的区间个数。

    先预处理出前缀最大值和后缀最大值和ST表,然后分治。

    每次可以得到这次分治区间的区间最大值,然后我们要求出以该最大值为区间最大值时的合法区间数目。

    这里我们可以枚举合法区间的左端点(右端点),然后通过化简上式得到合法的右端点(左端点),选择枚举左还是右端点由当前区间最大值的位置所决定,因为左端点一定在最大值左边,右端点一定在最大值右边,所以选择数量较小的一边来枚举。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<set>
     6 using namespace std;
     7 typedef long long ll;
     8 typedef unsigned long long ull;
     9 const int maxn = 3e5 + 110;
    10 int a[maxn], pos[maxn], L[maxn], R[maxn], Log[maxn];
    11 int n, k;
    12 int dp[maxn][20];
    13 int query(int l, int r) {
    14     int k = Log[r - l + 1];
    15     if (a[dp[l][k]] > a[dp[r - (1 << k) + 1][k]])
    16         return dp[l][k];
    17     else
    18         return dp[r - (1 << k) + 1][k];
    19 }
    20 ll dfs(int l, int r) {
    21     if (l == r)return a[l] - 1 <= k;
    22     if (l > r)return 0;
    23     int cnt = query(l, r);
    24     ll ans = 0;
    25     if (cnt - l < r - cnt) {
    26         for (int i = l; i <= cnt; i++) {
    27             int ls = max(cnt, i + a[cnt] - k - 1);
    28             int rs = min(r, R[i]);
    29             if (rs >= ls)
    30                 ans += rs - ls + 1;
    31         }
    32     }
    33     else {
    34         for (int i = cnt; i <= r; i++) {
    35             int ls = max(l, L[i]);
    36             int rs = min(i - (a[cnt] - k) + 1, cnt);
    37             if (rs >= ls) ans += rs - ls + 1;
    38         }
    39     }
    40     return ans + dfs(l, cnt - 1) + dfs(cnt + 1, r);
    41 }
    42 int main() {
    43     int t;
    44     scanf("%d", &t);
    45     while (t--) {
    46         scanf("%d%d", &n, &k);
    47         for (int i = 1; i <= n; i++)
    48             scanf("%d", &a[i]);
    49         Log[0] = -1;
    50         for (int i = 1; i <= n; i++) Log[i] = Log[i >> 1] + 1;
    51         for (int i = 1; i <= n; i++)
    52             dp[i][0] = i;
    53         for (int j = 1; (1 << j) <= n; j++) {
    54             for (int i = 1; i + (1 << j) - 1 <= n; i++) {
    55                 if (a[dp[i][j - 1]] > a[dp[i + (1 << (j - 1))][j - 1]])
    56                     dp[i][j] = dp[i][j - 1];
    57                 else
    58                     dp[i][j] = dp[i + (1 << (j - 1))][j - 1];
    59             }
    60         }
    61         for (int i = 0; i <= n; i++)pos[i] = 0;
    62         R[n + 1] = n;
    63         for (int i = n; i >= 1; i--) {
    64             if (pos[a[i]]) {
    65                 R[i] = pos[a[i]] - 1;
    66                 pos[a[i]] = i;
    67             }
    68             else {
    69                 pos[a[i]] = i;
    70                 R[i] = n;
    71             }
    72             R[i] = min(R[i], R[i + 1]);
    73         }
    74         for (int i = 0; i <= n; i++)pos[i] = 0;
    75         for (int i = 1; i <= n; i++) {
    76             if (pos[a[i]]) {
    77                 L[i] = pos[a[i]] + 1;
    78                 pos[a[i]] = i;
    79             }
    80             else {
    81                 pos[a[i]] = i;
    82                 L[i] = 1;
    83             }
    84             L[i] = max(L[i], L[i - 1]);
    85         }
    86         printf("%lld
    ", dfs(1, n));
    87     }
    88 }
  • 相关阅读:
    POJ 2492 并查集扩展(判断同性恋问题)
    菜鸟带你飞______DP基础26道水题
    HDU 1978 记忆化搜索(dfs+dp)
    HDU 1203 I NEED A OFFER (01背包&&概率dp)
    HDU 1176免费馅饼 DP数塔问题转化
    HDU 1069&&HDU 1087 (DP 最长序列之和)
    最短路&&最小生成树水题
    POJ 1797 Heavy Transportation (Dijkstra变形)
    数论学习笔记
    Codeforces Round #579 (Div. 3)
  • 原文地址:https://www.cnblogs.com/sainsist/p/11414393.html
Copyright © 2011-2022 走看看