• CH4301 Can youanswer on these queries III


    线段树裸题.

    描述
    给定长度为N的数列A,以及M条指令 (N≤500000, M≤100000),每条指令可能是以下两种之一:
    “2 x y”,把 A[x] 改成 y。
    “1 x y”,查询区间 [x,y] 中的最大连续子段和,即 max(x≤l≤r≤y)⁡ { ∑(i=l~r) A[i] }。
    对于每个询问,输出一个整数表示答案。

    输入格式
    第一行两个整数N,M

    第二行N个整数Ai

    接下来M行每行3个整数k,x,y,k=1表示查询(此时如果x>y,请交换x,y),k=2表示修改

    输出格式
    对于每个询问输出一个整数表示答案。

    样例输入
    5 3
    1 2 -3 4 5
    1 2 3
    2 2 -1
    1 3 2
    样例输出
    2
    -1
    数据范围与约定
    对于100%的数据: N≤500000, M≤100000, |Ai|<=1000

    线段树只需维护4个参数,ls,rs,res,sls,rs,res,s,分别表示区间从左起最大和,区间从右起最大和,区间最大连续子段和,区间和.

    维护函数:

    inline void upd(int x) {
    	s[x]=s[lc]+s[rc];
    	ls[x]=max(ls[lc],s[lc]+ls[rc]);
    	rs[x]=max(rs[rc],s[rc]+rs[lc]);
    	res[x]=max(max(res[lc],res[rc]),rs[lc]+ls[rc]);
    }
    

    查询的时候用两个变量:ans,tmpans,tmp即可.
    tmptmp表示右端点为当前线段树区间左端点-1的最大连续子段和.

    代码:

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #define g getchar()
    #define lc (x<<1)
    #define rc (x<<1|1)
    #define max(x,y) (x>y?x:y)
    using namespace std;
    typedef long long ll;
    const int N=1<<19;
    const ll inf=1LL<<63;
    template<class o>
    inline void qr(o&x) {
    	char c=g;x=0;int f=1;
    	while(!isdigit(c)){if(c=='-')f=-1;c=g;}
    	while(isdigit(c))x=x*10+c-'0',c=g;
    	x*=f;
    }
    void write(ll x) {
    	if(x/10)write(x/10);
    	putchar(x%10+'0');
    }
    void pri(ll x) {
    	if(x<0)putchar('-'),x=-x;
    	write(x);puts("");
    }
    
    template<typename o>
    inline void swap(o&x,o&y) { o t=x;x=y;y=t;}
    ll res[N<<1],ls[N<<1],rs[N<<1],s[N<<1];
    inline void upd(int x) {
    	s[x]=s[lc]+s[rc];
    	ls[x]=max(ls[lc],s[lc]+ls[rc]);
    	rs[x]=max(rs[rc],s[rc]+rs[lc]);
    	res[x]=max(max(res[lc],res[rc]),rs[lc]+ls[rc]);
    }
    void bt(int x,int l,int r) {
    	if(l==r){qr(s[x]);ls[x]=rs[x]=res[x]=s[x];return ;}
    	int mid=(l+r)>>1;
    	bt(lc,l,mid);
    	bt(rc,mid+1,r);
    	upd(x);
    }
    void change(int x,int l,int r,const int &pos,const ll &d) {
    	if(l==r){ls[x]=rs[x]=res[x]=s[x]=d;return ;}
    	int mid=(l+r)>>1;
    	if(pos<=mid)change(lc,l,mid,pos,d);
    	else 		change(rc,mid+1,r,pos,d);
    	upd(x);
    }
    ll ans,tmp;
    void query(int x,int l,int r,const int &L,const int &R) {
    	if(L<=l&&r<=R) {
    		ans=max(ans,max(res[x],tmp+ls[x]));
    		tmp=max(tmp+s[x],max(rs[x],0LL));
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(L<=mid)query(lc,l,mid,L,R);
    	if(mid< R)query(rc,mid+1,r,L,R);
    }
    int main() {
    	register int n,m;qr(n);qr(m);bt(1,1,n);
    	int op;ll l,r;
    	while(m--) {
    		qr(op),qr(l);qr(r);
    		switch(op) {
    			case 1:
    				if(l>r)swap(l,r);
    				ans=inf;tmp=0;
    				query(1,1,n,l,r);
    				pri(ans);break;
    			case 2:
    				change(1,1,n,l,r);
    				break;
    			}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Android 密匙库导出
    Android常用布局
    asp.net hessian + android hessdroid
    Android文件上传
    android,gridview
    Android文件下载
    Andriod 之数据获取
    java类的泛型DAO
    Spring之AOP编程
    mysql中如何统计某字段里某个字符的个数
  • 原文地址:https://www.cnblogs.com/zsyzlzy/p/12373880.html
Copyright © 2020-2023  润新知