• 「HNOI2016」序列


    「HNOI2016」序列

    传送门
    考虑莫队,瓶颈在于如何 (O(1)) 的更新扩展后区间的答案。
    我们只讨论左端点向左扩展的情况,其他情况类同。
    假设从 ([l + 1, r]) 扩展到 ([l, r]) ,那么也就多出了 ([l, l], [l, l + 1] cdots [l, r]) 这些区间,考虑计算这些区间的答案。
    首先找到这段区间的最小值所在位置 (p) ,那么右端点位于 ([p, r]) 的区间的答案都是 (a[p])
    另一部分用前缀和算:记 (f[i])(i) 为左端点时到后面位置的贡献这个可以用单调栈预处理一下然后从后往前转移:(f[i] = f[R[i]] + (R[i] - i) imes a[i])(R[i]) 表示右边第一个比 (a[i]) 小的数的位置。
    具体细节可以看代码。
    参考代码:

    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    #define rg register
    #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
    using namespace std;
    template < class T > inline void read(T& s) {
    	s = 0; int f = 0; char c = getchar();
    	while ('0' > c || c > '9') f |= c == '-', c = getchar();
    	while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
    	s = f ? -s : s;
    }
    
    typedef long long LL;
    const int _ = 1e5 + 5;
    
    int n, m, q, a[_], pos[_], lg[_];
    int top, stk[_], st[20][_], L[_], R[_]; LL fL[_], fR[_], res[_];
    struct node { int l, r, id; } t[_];
    inline bool cmp(const node& x, const node& y)
    { return pos[x.l] == pos[y.l] ? x.r < y.r : x.l < y.l; }
    
    inline int query(int l, int r) {
    	int x = lg[r - l + 1];
    	int A = st[x][l], B = st[x][r - (1 << x) + 1];
    	return a[A] <= a[B] ? A : B;
    }
    
    inline LL uptL(int l, int r) {
    	int p = query(l, r);
    	return fL[l] - fL[p] + 1ll * (r - p + 1) * a[p];
    }
    
    inline LL uptR(int l, int r) {
    	int p = query(l, r);
    	return fR[r] - fR[p] + 1ll * (p - l + 1) * a[p];
    }
    
    int main() {
    	read(n), read(q), m = sqrt(n);
    	for (rg int i = 1; i <= n; ++i) read(a[i]), pos[i] = (i - 1) / m + 1;
    	for (rg int i = 1; i <= q; ++i) read(t[i].l), read(t[i].r), t[i].id = i;
    	sort(t + 1, t + q + 1, cmp);
    	stk[top = 0] = 0;
    	for (rg int i = 1; i <= n; ++i) {
    		while (top && a[stk[top]] > a[i]) --top;
    		L[i] = stk[top], stk[++top] = i;
    	}
    	stk[top = 0] = n + 1;
    	for (rg int i = n; i >= 1; --i) {
    		while (top && a[stk[top]] > a[i]) --top;
    		R[i] = stk[top], stk[++top] = i;
    	}
    	for (rg int i = 1; i <= n; ++i) fR[i] = fR[L[i]] + 1ll * (i - L[i]) * a[i];
    	for (rg int i = n; i >= 1; --i) fL[i] = fL[R[i]] + 1ll * (R[i] - i) * a[i];
    	for (rg int i = 2; i <= n; ++i) lg[i] = lg[i >> 1] + 1;
    	for (rg int i = 1; i <= n; ++i) st[0][i] = i;
    	for (rg int i = 1; i <= lg[n]; ++i)
    		for (rg int j = 1; j + (1 << i) - 1 <= n; ++j) {
    			int A = st[i - 1][j], B = st[i - 1][j + (1 << (i - 1))];
    			st[i][j] = a[A] <= a[B] ? A : B;
    		}	
    	LL ans = 0;
    	for (rg int l = 1, r = 0, i = 1; i <= q; ++i) {
    		while (r < t[i].r) ans += uptR(l, ++r);
    		while (l > t[i].l) ans += uptL(--l, r);
    		while (r > t[i].r) ans -= uptR(l, r--);
    		while (l < t[i].l) ans -= uptL(l++, r);
    		res[t[i].id] = ans;
    	}
    	for (rg int i = 1; i <= q; ++i) printf("%lld
    ", res[i]);
    	return 0;
    }
    
  • 相关阅读:
    Jenkins+ansible+Gitlab集成环境搭建
    Jenkins 和常用工具集成
    Jenkins 安装部署及应用
    ansible 及相关应用
    gitlab 快速安装
    [持续交付实践] 交付流水线设计:基于测试脚本的线上拨测监控系统
    gitlab CICD
    Nginx判断UserAgent添加referer
    Nginx判断变量的配置
    golang 入门之环境搭建
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12231651.html
Copyright © 2020-2023  润新知