zoukankan      html  css  js  c++  java
  • BZOJ3956: Count

    orz 出题人Gromah

    这道题我的算法和他的标解完全不一样,目前在bzoj上是第一名,空间开销也是当前最小的(截个图纪念一下)

    首先用单调栈$O(n)$地预处理出以每个点为左端点、右端点的可行点对个数。

    然后对于每个询问$[l, r]$中,我们找到其中权值最大的点,假设它是$p$

    然后可以发现一个性质,在$[l, r]$中的所有可行点对都不会穿过$p$,如果穿过的话因为$p$是权值最大的点所以不合法

    于是我们只要统计$[l, p - 1]$的所有点作为左端点时的合法点对和$[p + 1, r]$的所有点作为右端点时的合法点对数量即可

    用ST表维护区间最大值

    时间复杂度$O(nlogn + m)$,空间复杂度$O(nlogn)$

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <map>
     7 using namespace std;
     8 #define rep(i, l, r) for (int i = l; i <= r; i++)
     9 #define drep(i, r, l) for (int i = r; i >= l; i--)
    10 typedef long long ll;
    11 const int N = 3e5 + 8;
    12 int n, m, ty, logn, st[22][N], L[N], R[N], son[N], a[N], top, q[N];
    13 ll sumL[N], sumR[N];
    14 int getint()
    15 {
    16     char c; int num = 0, w = 1;
    17     for (c = getchar(); !isdigit(c) && c != '-'; c = getchar());
    18     if (c == '-') c = getchar(), w = -1;
    19     for (;isdigit(c); c = getchar()) num = num * 10 + c - '0';
    20     return num * w;
    21 }
    22 void init()
    23 {
    24     logn = (int)(log(n) / log(2.0));
    25     rep(i, 1, n)
    26     {
    27         son[i] = son[i - 1];
    28         if ((1 << son[i] + 1) <= i) son[i]++; 
    29     }
    30     rep(i, 1, n) st[0][i] = i;
    31     rep(i, 1, logn)
    32         rep(j, 1, n)
    33         {
    34             int x = st[i - 1][j], y = st[i - 1][j + (1 << i - 1)];
    35             if (a[x] > a[y]) st[i][j] = x;
    36             else st[i][j] = y;
    37         }
    38     q[top = 1] = 1;
    39     rep(i, 2, n)
    40     {
    41         while (top && a[i] > a[q[top]]) L[i]++, top--;
    42         if (top) L[i]++;
    43         while (top && a[i] >= a[q[top]]) top--;
    44         q[++top] = i;
    45     }
    46     rep(i, 1, n) sumL[i] = sumL[i - 1] + L[i];
    47     q[top = 1] = n;
    48     drep(i, n - 1, 1)
    49     {
    50         while (top && a[i] > a[q[top]]) R[i]++, top--;
    51         if (top) R[i]++;
    52         while (top && a[i] >= a[q[top]]) top--;
    53         q[++top] = i;   
    54     }
    55     rep(i, 1, n) sumR[i] = sumR[i - 1] + R[i];
    56 }
    57 int query(int l, int r)
    58 {
    59     int k = son[r - l + 1];
    60     int x = st[k][l], y = st[k][r - (1 << son[r - l + 1]) + 1];
    61     if (a[x] > a[y]) return x;
    62     return y;
    63 }
    64 ll solve(int l, int r)
    65 {
    66     int p = query(l, r);
    67     ll ret = sumR[p - 1] - sumR[l - 1] + sumL[r] - sumL[p];
    68     return ret;
    69 }
    70 int main()
    71 {
    72 #ifndef ONLINE_JUDGE
    73     freopen("input.txt", "r", stdin);
    74     //freopen("output.txt", "w", stdout);
    75 #endif
    76     scanf("%d%d%d", &n, &m, &ty);
    77     rep(i, 1, n) a[i] = getint();
    78     init();
    79     ll ans = 0;
    80     while (m--)
    81     {
    82         int l = getint(), r = getint(); 
    83         if (ty == 1) l = (l + ans - 1) % n + 1, r = (r + ans - 1) % n + 1;
    84         if (l > r) swap(l, r);
    85         ans = solve(l, r);
    86         printf("%lld
    ", ans);
    87     }
    88 #ifndef ONLINE_JUDGE
    89     fclose(stdin); fclose(stdout);
    90 #endif
    91     return 0;
    92 }
    BZOJ3956
  • 相关阅读:
    密码由6-12位数字或字母组成,密码哈希加密
    获得一个字符串的汉语拼音码
    WPF中ComboBox绑定数据库自动读取产生数据
    SQL存储过程生成顺序编码
    SQL 语句调用这个存储过程,生成顺序编码
    restful(1):序列化
    Django的CBV和FBV
    权限管理组件:rbac
    ModelForm组件和forms组件补充
    BBS+Blog项目代码
  • 原文地址:https://www.cnblogs.com/Dyzerjet/p/4452549.html
Copyright © 2011-2022 走看看