zoukankan      html  css  js  c++  java
  • SPOJ GSS2 Can you answer these queries II (线段树&离线)

    Can you answer these queries II

    这是一道线段树的题目,维护历史版本,给出N(<=100000)个数字(-100000<=x<=100000),要求求出在[l,r]区间里面的连续序列的最大值,并且重复的数字可以加入序列但是值不能再计算。

    本题明显使用线段树,它只存在询问而没有修改操作,离线相对于在线更好维护。

    定义s[i] = ai + ai+1 + ai+2 + ... an,以ai开头的数列的和,那么每次加入更新ai 那么s1,s2,...si都会相应的加一个ai,s[1~i]中出现过a[i]是不能重复加值的,那么为了避免重复加值,用pre[a[i]]表示a[i]上一次出现的位置,那么也就是s[pre[ai]+1]~s[i]这一个区间加上a[i],每一次更新a[i]都要记录历史版本的最大值和懒惰标记的最大值。

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N = 100010;
    const int M = 100010;
    const int C = 100001;
    long long res[N];
    int a[N],pre[N<<1],n,m;
    
    struct Que{
    	int l,r,ID;
    	bool operator < (const Que &rhs)const{return r < rhs.r;}
    }question[M];
    
    struct Tree{long long s,ms,d,md;}tree[N<<2];
    
    #define lson k<<1,l,mid
    #define rson k<<1|1,mid+1,r
    
    void processup(int k){
    	tree[k].s = max(tree[k<<1].s,tree[k<<1|1].s);
    	tree[k].ms = max(tree[k<<1].ms,tree[k<<1|1].ms);
    }
    
    void processdown(int k){
    	if(!tree[k].d && !tree[k].md)return;
    	tree[k<<1].ms = max(tree[k<<1].ms,tree[k<<1].s+tree[k].md);
    	tree[k<<1].md = max(tree[k<<1].md,tree[k<<1].d+tree[k].md);
    	tree[k<<1].s += tree[k].d,tree[k<<1].d += tree[k].d;
    	
    	tree[k<<1|1].ms = max(tree[k<<1|1].ms,tree[k<<1|1].s+tree[k].md);
    	tree[k<<1|1].md = max(tree[k<<1|1].md,tree[k<<1|1].d+tree[k].md);
    	tree[k<<1|1].s += tree[k].d,tree[k<<1|1].d += tree[k].d;
    	
    	tree[k].d = tree[k].md = 0;
    }
    
    long long query(int k,int l,int r,int xl,int xr){
    	if(l == xl && r == xr)return tree[k].ms;
    	processdown(k);
    	int mid = (l+r)>>1;
    	if(xr <= mid)return query(lson,xl,xr);
    	else if(xl > mid)return query(rson,xl,xr);
    	else return max(query(lson,xl,mid),query(rson,mid+1,xr));
    	processup(k);
    }
    
    void update(int k,int l,int r,int xl,int xr,long long x){
    	if(l == xl && r == xr){
    		tree[k].s += x;
    		tree[k].d += x;
    		tree[k].ms = max(tree[k].ms,tree[k].s);
    		tree[k].md = max(tree[k].md,tree[k].d);
    		return;
    	}
    	processdown(k);
    	int mid = (l+r)>>1;
    	if(xr <= mid)update(lson,xl,xr,x);
    	else if(xl > mid)update(rson,xl,xr,x);
    	else update(lson,xl,mid,x),update(rson,mid+1,xr,x);
    	processup(k);
    }
    
    #define clr(a,b) memset(a,b,sizeof(a))
    
    int main(){
    	while(scanf("%d",&n) == 1){
    		clr(tree,0),clr(pre,0);
    		for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
    		scanf("%d",&m);
    		for(int i = 1;i <= m;++i){
    			scanf("%d%d",&question[i].l,&question[i].r);
    			question[i].ID = i;
    		}
    		sort(question+1,question+m+1);
    		int ID = 1;
    		for(int i = 1;i <= n;++i){
    			update(1,1,n,pre[a[i]+C]+1,i,a[i]);
    			pre[a[i]+C] = i;
    			while(ID <= m && question[ID].r == i){
    				res[question[ID].ID] = query(1,1,n,question[ID].l,question[ID].r);
    				ID++;
    			}
    		}
    		for(int i = 1;i <= m;++i)printf("%lld
    ",res[i]);
    	}
    	return 0;
    }
    

      

      

  • 相关阅读:
    牛客-编程题
    Python 实现一键发布项目
    IDEA MyBatis Log Plugin 收费了,这个可以替代用
    微信 for Windows 内测3.3.0版本,能刷朋友圈啦!
    实况摄像头,“偷窥” 世界美景!
    阿里云盘PC/MAC客户端内测版
    我十年前的工位 vs 我现在的工位
    设置电脑屏保全屏显示时间,酷!
    自我介绍
    Bartender 处理日期格式化
  • 原文地址:https://www.cnblogs.com/xgtao984/p/5721033.html
Copyright © 2011-2022 走看看