• CF1117G Recursive Queries


    题意:给定一个序列,定义[l, r]的最大值在m处,求f(l, r) = f(l, m - 1) + (r - l + 1) + f(m + 1, r)。多次询问。100w。

    解:考虑这个区间内每个数作为最大值的时候,它的(r - l + 1)的贡献。

    显然就是min(r, rci - 1) - max(l, lci + 1) + 1

    我们分别计算这两部分。

    min(r, rci - 1)这个东西,发现当一个i的rci - 1比r小的时候,就会是一个定值。否则就是r。而我们要区间求和,于是开一个线段树。把询问挂在区间上从右往左扫,线段树每个位置维护rci - 1是否比当前的r小。如果比当前r大了,就改掉。

    第二项同理。

      1 #include <bits/stdc++.h>
      2 
      3 typedef long long LL;
      4 
      5 const int N = 1000010;
      6 
      7 struct Node {
      8     int l, r, id;
      9 }node[N];
     10 
     11 int val[N], n, q, lc[N], rc[N], stk[N], top;
     12 LL ans[N];
     13 
     14 std::vector<int> v[N], v2[N];
     15 
     16 LL sum[N << 2], sum2[N << 2];
     17 
     18 inline void pushup(int o) {
     19     sum[o] = sum[o << 1] + sum[o << 1 | 1];
     20     sum2[o] = sum2[o << 1] + sum2[o << 1 | 1];
     21     return;
     22 }
     23 
     24 void build(int f, int l, int r, int o) {
     25     if(l == r) {
     26         if(f == 1) {
     27             sum[o] = lc[r] + 1;
     28         }
     29         else {
     30             sum[o] = rc[r] - 1;
     31         }
     32         sum2[o] = 0;
     33         return;
     34     }
     35     int mid = (l + r) >> 1;
     36     build(f, l, mid, o << 1);
     37     build(f, mid + 1, r, o << 1 | 1);
     38     pushup(o);
     39     return;
     40 }
     41 
     42 LL ask(int L, int R, int v, int l, int r, int o) {
     43     if(L <= l && r <= R) {
     44         return sum[o] + v * sum2[o];
     45     }
     46     int mid = (l + r) >> 1;
     47     LL ans = 0;
     48     if(L <= mid) ans = ask(L, R, v, l, mid, o << 1);
     49     if(mid < R) ans += ask(L, R, v, mid + 1, r, o << 1 | 1);
     50     return ans;
     51 }
     52 
     53 void change(int p, int l, int r, int o) {
     54     if(l == r) {
     55         sum[o] = 0;
     56         sum2[o] = 1;
     57         return;
     58     }
     59     int mid = (l + r) >> 1;
     60     if(p <= mid) change(p, l, mid, o << 1);
     61     else change(p, mid + 1, r, o << 1 | 1);
     62     pushup(o);
     63     return;
     64 }
     65 
     66 int main() {
     67 
     68     scanf("%d%d", &n, &q);
     69     for(int i = 1; i <= n; i++) {
     70         scanf("%d", &val[i]);
     71     }
     72 
     73     for(int i = 1; i <= q; i++) {
     74         scanf("%d", &node[i].l);
     75         node[i].id = i;
     76     }
     77     for(int i = 1; i <= q; i++) {
     78         scanf("%d", &node[i].r);
     79     }
     80 
     81     for(int i = 1; i <= n; i++) {
     82         while(top && val[stk[top]] <= val[i]) {
     83             rc[stk[top]] = i;
     84             top--;
     85         }
     86         lc[i] = stk[top];
     87         stk[++top] = i;
     88     }
     89     while(top) {
     90         rc[stk[top]] = n + 1;
     91         top--;
     92     }
     93     
     94     /// solve L 
     95     for(int i = 1; i <= n; i++) {
     96         v[lc[i]].push_back(i);
     97     }
     98     for(int i = 1; i <= q; i++) {
     99         v2[node[i].l].push_back(i);
    100     }
    101     
    102     
    103     build(1, 1, n, 1);
    104     for(int i = 1; i <= n; i++) {
    105         for(int j = 0; j < (int)v[i - 1].size(); j++) {
    106             /// v[i - 1][j] 
    107             change(v[i - 1][j], 1, n, 1);
    108         }
    109         for(int j = 0; j < (int)v2[i].size(); j++) {
    110             int x = v2[i][j];
    111             ans[x] = -ask(node[x].l, node[x].r, i, 1, n, 1);
    112         }
    113     }
    114     
    115     /// solve R 
    116     for(int i = 0; i <= n; i++) {
    117         v[i].clear();
    118         v2[i].clear();
    119     }
    120     for(int i = 1; i <= n; i++) {
    121         v[rc[i]].push_back(i);
    122     }
    123     for(int i = 1; i <= q; i++) {
    124         v2[node[i].r].push_back(i);
    125     }
    126     build(2, 1, n, 1);
    127     for(int i = n; i >= 1; i--) {
    128         for(int j = 0; j < (int)v[i + 1].size(); j++) {
    129             /// v[i + 1][j] 
    130             change(v[i + 1][j], 1, n, 1);
    131         }
    132         for(int j = 0; j < (int)v2[i].size(); j++) {
    133             int x = v2[i][j];
    134             ans[x] += ask(node[x].l, node[x].r, i, 1, n, 1);
    135         }
    136     }
    137     
    138     for(int i = 1; i <= q; i++) {
    139         printf("%lld ", ans[i] + node[i].r - node[i].l + 1);
    140     }
    141     
    142     return 0;
    143 }
    AC代码
  • 相关阅读:
    C语言I博客作业06
    C语言I博客作业05
    C语言I博客作业04
    C语言II博客作业04
    C语言II博客作业03
    C语言II博客作业02
    C语言II博客作业01
    期末总结
    第一次作业
    C语言I博客作业08
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10800012.html
Copyright © 2020-2023  润新知