4540: [Hnoi2016]序列

4540: [Hnoi2016]序列

https://www.lydsy.com/JudgeOnline/problem.php?id=4540

分析:

  莫队+RMQ+单调栈。

  考虑加入一个点后,区间发生了什么变化。[l,r]->[l,r+1],增加了r-l+1段区间。设[l,r+1]的最小值在p,那么左端点在l~p-1的区间,答案就是a[p]了,p右边同样

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8 #include<vector>
 9 #include<queue>
10 #include<map>
11 #define fi(s) freopen(s,"r",stdin);
12 #define fo(s) freopen(s,"w",stdout);
13 using namespace std;
14 typedef long long LL;
15 
16 inline int read() {
17     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
18     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
19 }
20 
21 const int N = 100005;
22 
23 int a[N], sk[N], bel[N], L[N], R[N], f[N][20], Log[N];
24 LL ans[N], sl[N], sr[N], Answer;
25 struct Que{
26     int l, r, id;
27     bool operator < (const Que &A) const {
28         return bel[l] == bel[A.l] ? r < A.r : bel[l] < bel[A.l];
29     }
30 }q[N];
31 
32 inline int Min(int i,int j) {
33     return a[i] < a[j] ? i : j;
34 }
35 inline int Calc(int l,int r) {
36     if (r < l) swap(l, r);
37     int t = Log[r - l + 1];
38     return Min(f[l][t], f[r - (1 << t) + 1][t]);
39 }
40 inline void updl(int l,int r,int o) {
41     int p = Calc(l, r);
42     LL t = 1ll * a[p] * (r - p + 1) + sr[l] - sr[p];
43     Answer += o * t;
44 }
45 inline void updr(int l,int r,int o) {
46     int p = Calc(l, r);
47     LL t = 1ll * a[p] * (p - l + 1) + sl[r] - sl[p];
48     Answer += o * t;
49 }
50 int main() { fi("1.txt");
51     int n = read(), Q = read(), B = sqrt(n); Log[0] = -1;
52     for (int i=1; i<=n; ++i) {
53         a[i] = read();
54         bel[i] = (i - 1) / B + 1;
55         Log[i] = Log[i >> 1] + 1;
56         f[i][0] = i;
57     }
58     for (int i=1; i<=Q; ++i) 
59         q[i].l = read(), q[i].r = read(), q[i].id = i;
60     
61     for (int j=1; j<=Log[n]; ++j) 
62         for (int i=1; i+(1<<j)-1<=n; ++i) 
63             f[i][j] = Min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
64     
65     int top = 0;
66     for (int i=1; i<=n; ++i) {
67         while (top && a[sk[top]] >= a[i]) R[sk[top]] = i, top --;
68         sk[++top] = i;
69     }
70     while (top) R[sk[top]] = n + 1, top --;
71     for (int i=n; i>=1; --i) {
72         while (top && a[sk[top]] > a[i]) L[sk[top]] = i, top --;
73         sk[++top] = i;
74     }
75     while (top) L[sk[top]] = 0, top --;
76     
77     for (int i=1; i<=n; ++i) sl[i] = sl[L[i]] + 1ll * (i - L[i]) * a[i];
78     for (int i=n; i>=1; --i) sr[i] = sr[R[i]] + 1ll * (R[i] - i) * a[i];
79     
80     sort(q + 1, q + Q + 1);
81     int l = 1, r = 0;
82     for (int i=1; i<=Q; ++i) {
83         while (l > q[i].l) l --, updl(l, r, 1); // 先加在减!!! 
84         while (r < q[i].r) r ++, updr(l, r, 1);
85         while (l < q[i].l) updl(l, r, -1), l ++;
86         while (r > q[i].r) updr(l, r, -1), r --;
87         ans[q[i].id] = Answer;
88     }
89     for (int i=1; i<=Q; ++i) 
90         printf("%lld\n", ans[i]);
91     return 0;
92 }

猜你喜欢

转载自www.cnblogs.com/mjtcn/p/9765534.html