区间子序列查询

区间子序列查询

时间限制: 9 Sec 内存限制: 64 MB

题目描述
有n个整数,两种操作方式:
0 x y:查询[x,y]区间的最大子序列和,其中子序列中相邻元素的原下标奇偶性都不同。
1 x y:将x位置的数改成y。

输入
第一行一个整数T,表示测试点的个数。
对于每个测试点:
第一行两个整数n和m(n,m <= 100000),分别表示序列的长度和操作的次数。
第二行包含n个整数,a1,…,an(-1000000000 ≤ai≤1000000000)。
接下来m行,每行代表一次操作,包含3个整数:type x y。
当type=0时,输出[x,y]区间的最大子序列和,其中(1 <= a <= b <= n)。
当type=1时,将x位置的数改成y,其中(1 <= a <= n, 1 <= b <= 1e9)。

输出
对于每个操作0,请输出相应查询的答案。

样例输入
1
1 1
1
0 1 1

样例输出
1

来源
2015多校

题解

用线段树分别维护奇数位开始偶数位结束,奇数位开始奇数位结束,偶数位开始偶数位结束,偶数位开始奇数位结束四个值即可。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define N 100010
#define ll long long
#define inf 999999999999999999ll
using namespace std;
int Q,n,m,s[N];
struct node{ll sum1,sum2,sum3,sum4;}t[N*4];
//积积,积偶,偶积,偶偶 
class seg_tree
{
  void update(int x)
  {
    int lc=x<<1,rc=lc+1;
    t[x].sum1=max(t[lc].sum1+t[rc].sum3,max(t[lc].sum2+t[rc].sum1,max(t[lc].sum1,t[rc].sum1)));
    t[x].sum2=max(t[lc].sum1+t[rc].sum4,max(t[lc].sum2+t[rc].sum2,max(t[lc].sum2,t[rc].sum2)));
    t[x].sum3=max(t[lc].sum3+t[rc].sum3,max(t[lc].sum4+t[rc].sum1,max(t[lc].sum3,t[rc].sum3)));
    t[x].sum4=max(t[lc].sum3+t[rc].sum4,max(t[lc].sum4+t[rc].sum2,max(t[lc].sum4,t[rc].sum4)));
  }
  public:
  void build(int x,int l,int r)
  {
    t[x].sum1=-inf;t[x].sum2=-inf;
    t[x].sum3=-inf;t[x].sum4=-inf;
    if(l==r)
    {
      if(l&1)t[x].sum1=(ll)s[l];
      else t[x].sum4=(ll)s[l];return;
    }
    int mid=l+r>>1,lc=x<<1,rc=lc+1;
    build(lc,l,mid);build(rc,mid+1,r);update(x);
  }
  void modify(int x,int l,int r,int des,int num)
  {
    if(l==r)
    {
      if(l&1)t[x].sum1=(ll)num;
      else t[x].sum4=(ll)num;return;
    }
    int mid=l+r>>1,lc=x<<1,rc=lc+1;
    if(des<=mid)modify(lc,l,mid,des,num);
    else modify(rc,mid+1,r,des,num);update(x);
  }
  node qry(int x,int l,int r,int ql,int qr)
  {
    if(ql==l&&r==qr)return t[x];
    int mid=l+r>>1,lc=x<<1,rc=lc+1;
    if(qr<=mid)return qry(lc,l,mid,ql,qr); if(ql>mid)return qry(rc,mid+1,r,ql,qr);
    node t1=qry(lc,l,mid,ql,mid),t2=qry(rc,mid+1,r,mid+1,qr),res;
    res.sum1=max(t1.sum1+t2.sum3,max((t1.sum2+t2.sum1),max(t1.sum1,t2.sum1)));
    res.sum2=max(t1.sum1+t2.sum4,max((t1.sum2+t2.sum2),max(t1.sum2,t2.sum2)));
    res.sum3=max(t1.sum3+t2.sum3,max((t1.sum4+t2.sum1),max(t1.sum3,t2.sum3)));
    res.sum4=max(t1.sum3+t2.sum4,max((t1.sum4+t2.sum2),max(t1.sum4,t2.sum4)));
    return res;
  }
}T;

int main()
{
  int type,a,b;
  scanf("%d",&Q);
  while(Q--)
  {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&s[i]);
    T.build(1,1,n);
    while(m--)
    {
      scanf("%d%d%d",&type,&a,&b);
      if(type)T.modify(1,1,n,a,b);
      else
      {
        node p=T.qry(1,1,n,a,b);
        printf("%lld\n",max(p.sum4,max(p.sum3,max(p.sum1,p.sum2))));
      }
    }
  }
  return 0;
}

你可能感兴趣的:(区间子序列查询)