您的位置:首页 > 其它

HDU 5316 Magician

2015-07-28 20:34 253 查看
题意:给你一个数列,然后要有两种操作。操作1 x y 代表把数列的第x个数字改成y

    操作0 x y 代表在a[x]....a[y]间找到一个beautiful 子序列的和最大

beautiful 子序列就是相邻的两个数在原来的数列的位置的奇偶性不一样

如a[1],a[4],a[5]就是,但a[2],a[4],就不是,因为2、4的奇偶性一样。

思路:线段树,用一个结构体去保存某段的beautiful序列的最大和

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<math.h>
#include<string>
using namespace std;
#pragma comment (linker, "/STACK:1024000000,1024000000")
typedef long long ll;
const int N = 100005;
const ll INF = 100000000000000;
struct node{
ll v[2][2];			//v[0][1]  代表偶数位开头,奇数位结尾的beautiful序列的最大和
ll vmax(){
ll temp = -INF;
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
temp = max(v[i][j], temp);
}
}
return temp;
}
}t[N<<2];
int n,Q,k;
void pushup(int rt){
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
t[rt].v[i][j] = max(t[rt<<1].v[i][j], t[rt<<1|1].v[i][j]);
t[rt].v[i][j] = max(t[rt].v[i][j], t[rt<<1].v[i][j^1] + t[rt<<1|1].v[j][j]);
t[rt].v[i][j] = max(t[rt].v[i][j], t[rt<<1].v[i][j] + t[rt<<1|1].v[j^1][j]);
//t[rt].v[i][j] = max(t[rt].v[i][j], 0LL);	//此处被坑了,子序列不能不取啊,就是就算是负数也要取,本以为负数就不取,就是0了
}
}
}
void update(int rt,int l,int r,int x,int val){
if(l==r){
if(x&1)t[rt].v[1][1] = val;
else t[rt].v[0][0] = val;
return;
}
int mid=(l+r)>>1;
if(x<=mid)update(rt<<1, l, mid, x, val);
else update(rt<<1|1, mid+1, r, x, val);
pushup(rt);
}
node query(int rt,int l,int r,int x,int y){
if(x<=l&&r<=y){
return t[rt];
}
int mid=(l+r)>>1;
node ans1, ans2, ret;
bool flag1 = false, flag2 = false;
if(x <= mid){
ans1 = query(rt<<1, l, mid, x, y);
flag1 = true;
}
if(y > mid){
ans2 = query(rt<<1|1, mid+1, r, x, y);
flag2 = true;
}
if(!flag1&&flag2){
return ans2;
}
else if(!flag2&&flag1){
return ans1;
}
else if(flag1 && flag2){
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++){
ret.v[i][j] = max(ans1.v[i][j], ans2.v[i][j]);
ret.v[i][j] = max(ret.v[i][j], ans1.v[i][j^1] + ans2.v[j][j]);
ret.v[i][j] = max(ret.v[i][j], ans1.v[i][j] + ans2.v[j^1][j]);
//ret.v[i][j] = max(ret.v[i][j], 0LL);
}
}
return ret;
}
}
void build(int rt, int l, int r){
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)t[rt].v[i][j] = -INF;
if(l == r){
ll x;
scanf("%I64d",&x);
if(l&1)t[rt].v[1][1] = x;
else t[rt].v[0][0] = x;
return ;
}
int mid = (l+r)>>1;
build(rt<<1, l, mid);
build(rt<<1|1, mid+1,r);
pushup(rt);
}
void work(){
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
k=0;
scanf("%d%d",&n,&Q);
build(1,1,n);
while(Q--){
int u,x,y;
scanf("%d%d%d",&u,&x,&y);
if(u == 0){
node ans = query(1,1,n,x,y);
printf("%I64d\n",ans.vmax());
}
else {
update(1,1,n,x,y);
}
}
}
}
int main(){
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU 线段树