1. 程式人生 > >4540: [Hnoi2016]序列

4540: [Hnoi2016]序列

\n cto return ctype getch using string swa mes

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 }

4540: [Hnoi2016]序列