• SP1557 GSS2 Can you answer these queries II


    求区间最大子段和,而且不能有重复元素的
    为了避免重复元素,我们用扫描线

    把所有询问离线下来,按照r升序排序

    对于一个元素a[i],每次扫描到,就在pre[a[i]]+1~i 加入元素 a[i],然后查询查询区间的历史区间最大值,然后这个历史区间最大值就是[l,l+1],[l,l+2]***[l,r]的
    最大子段和就是在[l],[l+1][r]这些左端点的区间的最大值里面挑选最大值
    我们查询[l,r]的历史区间最值就是这个max([l,l],[l,l + 1],[l,l + 2].....[l,r])里面的历史区间最值,就是[l,.........] [l + 1.......] [l + 2.............] [r,......]的最大值
    可能就是这样吧。

    const int N = 1e5 + 79;
    int a[N], q, n;
    struct question {
    	int l, r, id;
    	inline bool operator <(const question &rhs) {
    		return r < rhs.r;
    	}
    } t[N];
    int pre[N * 2];
    struct SegmentTree {
    	lxl mx[N << 1], Hismx[N << 1], tag[N << 1], Histag[N << 1];
    	int lc[N << 1], rc[N << 1], rt, cnt;
    
    	inline void pushup(int p) {
    		mx[p] = max(mx[lc[p]], mx[rc[p]]);
    		Hismx[p] = max(Hismx[lc[p]], Hismx[rc[p]]);
    		tag[p] = Histag[p] = 0;
    	}
    	inline void pushdown(int p) {
    		if(tag[p] == 0 && Histag[p] == 0) return ;
    
    		if(!lc[p]) lc[p] = ++cnt;
    		Hismx[lc[p]] = max(Hismx[lc[p]], mx[lc[p]] + Histag[p]);
    		Histag[lc[p]] = max(Histag[lc[p]], tag[lc[p]] + Histag[p]);
    		mx[lc[p]] += tag[p];
    		tag[lc[p]] += tag[p];
    
    		if(!rc[p]) rc[p] = ++cnt;
    
    		Hismx[rc[p]] = max(Hismx[rc[p]], mx[rc[p]] + Histag[p]);
    		Histag[rc[p]] = max(Histag[rc[p]], tag[rc[p]] + Histag[p]);
    		mx[rc[p]] += tag[p];
    		tag[rc[p]] += tag[p];
    
    		tag[p] = Histag[p] = 0;
    	}
    
    
    	inline void add(int &p, int L, int R, int ll, int rr, lxl val) {
    		if(!p) p = ++cnt;
    		if(ll <= L && rr >= R) {
    			mx[p] += val;
    			Hismx[p] = max(Hismx[p], mx[p]);
    			tag[p] += val;
    			Histag[p] = max(Histag[p], tag[p]);
    			return ;
    		}
    		pushdown(p);
    		int mid(L + R >> 1);
    		if(ll <= mid) add(lc[p], L, mid, ll, rr, val);
    		if(rr > mid) add(rc[p], mid + 1, R, ll, rr, val);
    		pushup(p);
    	}
    
    	inline lxl query(int &p, int L, int R, int ll, int rr) {
    		if(!p) return -1e18;
    		if(ll <= L && rr >= R) {
    			return Hismx[p];
    		}
    		pushdown(p);
    		int mid(L + R >> 1);
    		lxl ans = -1e18;
    		if(ll <= mid) ans = max(ans, query(lc[p], L, mid, ll, rr));
    		if(rr > mid) ans = max(ans, query(rc[p], mid + 1, R, ll, rr));
    		return ans;
    	}
    } S;
    
    
    lxl ans[N];
    int main() {
    	read(n);
    	rep(i, 1, n) {
    		read(a[i]);
    	}
    	read(q);
    	rep(i, 1, q) {
    		read(t[i].l);
    		read(t[i].r);
    		t[i].id = i;
    	}
    	std::sort(t + 1, t + q + 1);
    
    	int j(1);
    	rep(i, 1, n) {
    		S.add(S.rt, 1, n, pre[a[i] + 100000] + 1, i, a[i]);
    		pre[a[i] + 100000] = i;
    		while(t[j].r == i && j <= q) {
    			ans[t[j].id] = S.query(S.rt, 1, n, t[j].l, t[j].r);
    			++j;
    		}
    	}
    
    	rep(i, 1, q) {
    		out(ans[i], '\n');
    	}
    	return 0;
    }
    

    本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15572939.html

  • 相关阅读:
    「10.10」神炎皇(欧拉函数)·降雷皇(线段树,DP)·幻魔皇
    「10.8」simple「数学」·walk「树上直径」
    10.5「嘟嘟噜」·「天才绅士少女助手克里斯蒂娜」·「凤凰院凶真」
    csp-s模拟测试59(10.4)「Reverse」(set)·「Silhouette」(容斥)
    csp-s模拟测试58「Divisors」·「Market」·「Dash Speed」
    csp-s模拟测试57(10.2)「天空龙」·「巨神兵」·「太阳神」
    csp-s模拟测试56(10.2)Merchant「二分」·Equation「树状数组」
    csp-s模拟测试55(9.29)联「线段树」·赛「??」题「神仙DP」
    消防(树上直径)
    模拟测试65
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15572939.html
Copyright © 2020-2023  润新知