1 1 1 1 0 1 1
1
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include <algorithm>
#include <vector>
#include <map>
#define PI acos(-1.0)
#define M 1000005 //10^6
#define eps 1e-8
#define LL long long
#define moo 1000000007
#define INF -999999999
using namespace std;
struct Node
{
int has[2][2];//存是否有这种情况,0代表无1代表有
long long ma[2][2];//存该情况的最大值
//[i][j]为i始j终的情况,i、j为0则是偶,i、j为1则是奇
}tre[100000*4];
//合并操作
Node uni(Node a,Node b)
{
Node c;
//首先 四种起始和终止情况可以直接继承于左儿子或右儿子的对应情况,取最大
for(int i=0;i<=1;i++)
for(int j=0;j<=1;j++)
{
c.has[i][j]=a.has[i][j]|b.has[i][j];
if(a.has[i][j]&&b.has[i][j])
c.ma[i][j]=max(a.ma[i][j],b.ma[i][j]);
else if(a.has[i][j])
c.ma[i][j]=a.ma[i][j];
else if(b.has[i][j])
c.ma[i][j]=b.ma[i][j];
}
//其次 四种情况也可以由左儿子和右儿子的情况合并起来。
//例如奇始奇终可以由左儿子的奇始偶终和右儿子的奇始奇终合并,也可以由左儿子的奇始奇终和右儿子的偶始奇终合并,以此类推
for(int i=0;i<=1;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
if(a.has[i][j]&&b.has[!j][k])
if(c.has[i][k])
c.ma[i][k]=max(c.ma[i][k],a.ma[i][j]+b.ma[!j][k]);
else
c.has[i][k]=1,c.ma[i][k]=a.ma[i][j]+b.ma[!j][k];
return c;
}
//初始化线段树,父节点的值是由子节点的合并而来
void build(int num,int le,int ri)
{
memset(tre[num].has,0,sizeof(tre[num].has));
if(le==ri)
{
int a;
scanf("%d",&a);
tre[num].has[le%2][le%2]=1;
tre[num].ma[le%2][le%2]=a;
return ;
}
int mid=(le+ri)/2;
build(num*2,le,mid);
build(num*2+1,mid+1,ri);
tre[num]=uni(tre[num*2],tre[num*2+1]);
}
//修改操作,跟build基本没任何区别
void update(int num,int le,int ri,int x,int y)
{
if(le==ri)
{
memset(tre[num].has,0,sizeof(tre[num].has));
tre[num].has[le%2][le%2]=1;
tre[num].ma[le%2][le%2]=y;
return ;
}
int mid=(le+ri)/2;
if(x<=mid)
update(num*2,le,mid,x,y);
else
update(num*2+1,mid+1,ri,x,y);
tre[num]=uni(tre[num*2],tre[num*2+1]);
}
//查询操作,按照区间查询,然后把左右查的结果合并起来(如果有的话)
Node query(int num,int le,int ri,int x,int y)
{
if(x<=le&&y>=ri)
return tre[num];
int flag1=0,flag2=0;
Node x1,x2;
int mid=(le+ri)/2;
if(x<=mid)
x1=query(num*2,le,mid,x,y),flag1=1;
if(y>mid)
x2=query(num*2+1,mid+1,ri,x,y),flag2=1;
if(flag1==0)
return x2;
if(flag2==0)
return x1;
return uni(x1,x2);
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n,m;
cin>>n>>m;
build(1,1,n);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(x==0)
{
Node t=query(1,1,n,y,z);
long long ans;
int flag=0;
//查询出来的判断四种情况哪种最大。
for(int i=0;i<=1;i++)
for(int j=0;j<=1;j++)
if(t.has[i][j])
if(flag==0)
ans=t.ma[i][j],flag=1;
else
ans=max(ans,t.ma[i][j]);
cout<<ans<<endl;
}
else
update(1,1,n,y,z);
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/zip_fan/article/details/47111379