• 洛谷P3722 [AH2017/HNOI2017]影魔(线段树)


    题意

    题目链接

    Sol

    题解好神仙啊qwq。

    一般看到这种考虑最大值的贡献的题目不难想到单调数据结构

    对于本题而言,我们可以预处理出每个位置左边第一个比他大的位置(l_i)以及右边第一个比他大的位置(r_i)

    那么((l_i, r_i))会产生(p1)的贡献

    ([l_i + 1, i - 1])(r_i)会产生(p2)的贡献

    ([i + 1, r_i - 1])(l_i)会产生(p2)的贡献

    这样我们直接上区间加线段树就能统计到每个点的贡献了。

    然后统计答案非常神仙,我们把询问拆开,当枚举到(l - 1)时,记此时([l,r])(sum)(s1),当枚举到(r)时,记此时([l, r])(sum)为s2,那么该询问的答案为(s2 - s1)

    复杂度:(O(nlogn))

    #include<bits/stdc++.h>
    #define LL long long 
    using namespace std;
    const int MAXN = 1e6 + 10, INF = 1e9 + 10;
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * f;
    }
    int N, M, p1, p2, a[MAXN], L[MAXN], R[MAXN];
    LL ans[MAXN];
    int ll[MAXN], rr[MAXN];
    LL sum[MAXN], f[MAXN];
    #define ls k << 1
    #define rs k << 1 | 1
    void ps(int k, int v) {
    	sum[k] += (rr[k] - ll[k] + 1) * v;
    	f[k] += v;
    }
    void pushdown(int k) {
    	if(!f[k]) return ;
    	ps(ls, f[k]); ps(rs, f[k]);
    	f[k] = 0;
    }
    void update(int k) {
    	sum[k] = sum[ls] + sum[rs];
    }
    void Build(int k, int l, int r) {
    	ll[k] = l; rr[k] = r;
    	if(l == r) return ;
    	int mid = l + r >> 1;
    	Build(ls, l, mid); Build(rs, mid + 1, r);
    }
    void IntAdd(int k, int l, int r, int ql, int qr, int v) {
    	if(ql > qr) return ;
    	if(ql <= l && r <= qr) {ps(k, v); return ;}
    	pushdown(k);
    	int mid = l + r >> 1;
    	if(ql <= mid) IntAdd(ls, l, mid, ql, qr, v);
    	if(qr  > mid) IntAdd(rs, mid + 1, r, ql, qr, v);
    	update(k);
    }
    LL IntQuery(int k, int l, int r, int ql, int qr) {
    	if(ql > qr) return 0;
    	if(ql <= l && r <= qr) return sum[k];
    	pushdown(k);
    	int mid = l + r >> 1;
    	if(ql > mid) return IntQuery(rs, mid + 1, r, ql, qr);
    	else if(qr <= mid) return IntQuery(ls, l, mid, ql, qr);
    	else return IntQuery(ls, l, mid, ql, qr) + IntQuery(rs, mid + 1, r, ql, qr);
    }
    struct Query {
    	int l, r, val, id;
    	bool operator < (const Query &rhs) const {
    		return id < rhs.id;
    	}
    };
    vector<Query> q[MAXN];
    void Pre() {
    	a[0] = INF; a[N + 1] = INF;
    	static int st[MAXN], top = 0;
    	for(int i = 1; i <= N + 1; i++) {
    		while(top && a[i] > a[st[top]]) R[st[top--]] = i;
    		L[i] = st[top];
    		st[++top] = i;
    	}
    	for(int i = 1; i <= N; i++) {
    		q[R[i]].push_back({L[i], L[i], p1, -R[i]});
    		q[L[i]].push_back({i + 1, R[i] - 1, p2, -L[i]});
    		q[R[i]].push_back({L[i] + 1, i - 1, p2, -R[i]});
    	}
    }
    
    int main() {
    	N = read(); M = read(); p1 = read(); p2 = read();
    	for(int i = 1; i <= N; i++) a[i] = read();
    	Pre();
    	Build(1, 0, N + 1);
    	for(int i = 1; i <= M; i++) {
    		int a = read(), b = read();
    		ans[i] = (b - a) * p1;
    		q[a - 1].push_back({a, b, -1, i});
    		q[b].push_back({a, b, 1, i});
    	}
    	for(int i = 0; i <= N; i++) {
    		sort(q[i].begin(), q[i].end());	
    		for(auto &x : q[i]) {
    			if(x.id < 0) IntAdd(1, 0, N + 1, x.l, x.r, x.val);
    			else ans[x.id] += 1ll * x.val * (IntQuery(1, 0, N + 1, x.l, x.r));
    		}
    	}
    	for(int i = 1; i <= M; i++) cout << ans[i] << "
    ";
    	return 0;
    }
    
  • 相关阅读:
    Clion 配置
    JetBrains 全套激活 Pycharm Clion 高校学生老师免费用
    VS Code 搭建 C/C++ 编译运行环境的四种方案 (待完善)
    专治编译器编辑器vscode中文乱码输出 win10 配置系统默认utf-8编码
    AlexeyAB大神版yolo 待完善
    Python 的 GUI 开发工具
    Python打包—Pyinstaller
    pip freeze 打包依赖库及setup.py
    jenkins中布置python测试
    在Ubuntu上安装Jenkins
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/10435145.html
Copyright © 2020-2023  润新知