1. 程式人生 > >hdu5316 Magician (線段樹+單點更新+區間查詢+區間合併)

hdu5316 Magician (線段樹+單點更新+區間查詢+區間合併)

Magician
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3084 Accepted Submission(s): 838

Problem Description
Fantasy magicians usually gain their ability through one of three usual methods: possessing it as an innate talent, gaining it through study and practice, or receiving it from another being, often a god, spirit, or demon of some sort. Some wizards are depicted as having a special gift which sets them apart from the vast majority of characters in fantasy worlds who are unable to learn magic.

Magicians, sorcerers, wizards, magi, and practitioners of magic by other titles have appeared in myths, folktales, and literature throughout recorded history, with fantasy works drawing from this background.

In medieval chivalric romance, the wizard often appears as a wise old man and acts as a mentor, with Merlin from the King Arthur stories representing a prime example. Other magicians can appear as villains, hostile to the hero.

Mr. Zstu is a magician, he has many elves like dobby, each of which has a magic power (maybe negative). One day, Mr. Zstu want to test his ability of doing some magic. He made the elves stand in a straight line, from position 1 to position n, and he used two kinds of magic, Change magic and Query Magic, the first is to change an elf’s power, the second is get the maximum sum of beautiful subsequence of a given interval. A beautiful subsequence is a subsequence that all the adjacent pairs of elves in the sequence have a different parity of position. Can you do the same thing as Mr. Zstu ?

Input
The first line is an integer T represent the number of test cases.
Each of the test case begins with two integers n, m represent the number of elves and the number of time that Mr. Zstu used his magic.
(n,m <= 100000)
The next line has n integers represent elves’ magic power, magic power is between -1000000000 and 1000000000.
Followed m lines, each line has three integers like
type a b describe a magic.
If type equals 0, you should output the maximum sum of beautiful subsequence of interval [a,b].(1 <= a <= b <= n)
If type equals 1, you should change the magic power of the elf at position a to b.(1 <= a <= n, 1 <= b <= 1e9)

Output
For each 0 type query, output the corresponding answer.

Sample Input

1
1 1
1
0 1 1

Sample Output

1

題意:給你n個數,有兩種操作:
1ab 將下標為a的數變為b
0lr[l,r]內的一組數,這組數相鄰的數的下標的奇偶性不同,求這組數的最大和.

思路:滿足條件的一組數的首尾可能有四種情況:奇奇、奇偶、偶偶、偶奇,所以說,我們線上段樹中加上這四種情況來維護,在區間查詢和單點查詢的時候和平常的一樣,加上了一個區間合併。

ac程式碼:

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#define MAXN 1010000
#define LL long long
#define ll __int64
#define INF 0x7fffffff
#define mem(x) memset(x,0,sizeof(x))
#define PI acos(-1)
#define eps 1e-8
using namespace std;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
double dpow(double a,ll b){double ans=1.0;while(b){if(b%2)ans=ans*a;a=a*a;b/=2;}return ans;}
//head
struct s
{
    ll lc,rc,jj,jo,oo,oj;
}tree[MAXN],kk;
ll num[MAXN];
s findmax(int i,s A,s B)
{
    s k;ll a,b,c,d;
    a=max(A.jj,B.jj);a=max(a,A.jj+B.oj);a=max(a,A.jo+B.jj);
    b=max(A.jo,B.jo);b=max(b,A.jo+B.jo);b=max(b,A.jj+B.oo);
    c=max(A.oo,B.oo);c=max(c,A.oo+B.jo);c=max(c,A.oj+B.oo);
    d=max(A.oj,B.oj);d=max(d,A.oj+B.oj);d=max(d,A.oo+B.jj);
    tree[i].jj=a;tree[i].jo=b;tree[i].oo=c;tree[i].oj=d;
    return k;
}
s getmax(s A,s B)
{
    s k;ll a,b,c,d;
    a=max(A.jj,B.jj);a=max(a,A.jj+B.oj);a=max(a,A.jo+B.jj);
    b=max(A.jo,B.jo);b=max(b,A.jo+B.jo);b=max(b,A.jj+B.oo);
    c=max(A.oo,B.oo);c=max(c,A.oo+B.jo);c=max(c,A.oj+B.oo);
    d=max(A.oj,B.oj);d=max(d,A.oj+B.oj);d=max(d,A.oo+B.jj);
    k.jj=a;k.jo=b;k.oo=c;k.oj=d;
    return k;
}
void build(int i,ll l,ll r)
{
    tree[i].lc=l,tree[i].rc=r;
    if(l==r)
    {
        if(l%2)
        {
            tree[i].jj=num[l];tree[i].jo=-INF;
            tree[i].oo=-INF;tree[i].oj=-INF;
        }
        else
        {
            tree[i].jj=-INF;tree[i].jo=-INF;
            tree[i].oo=num[l];tree[i].oj=-INF;
        }
        return ;
    }
    else
    {
        int mid=(l+r)/2;
        build(i*2,l,mid);build(i*2+1,mid+1,r);
        findmax(i,tree[i*2],tree[i*2+1]);
    }
}
void update(ll aa,ll b,int i)
{
    if(tree[i].lc==tree[i].rc&&tree[i].lc==aa)
    {
        if(aa%2) tree[i].jj=b;
        else tree[i].oo=b;
        return;
    }
    ll mid=(tree[i].lc+tree[i].rc)/2;
    if(mid>=aa)
        update(aa,b,i*2);
    else
        update(aa,b,i*2+1);
    findmax(i,tree[i*2],tree[i*2+1]);
}
s query(int i,ll l,ll r)
{
    if(tree[i].lc==l&&tree[i].rc==r)
        return tree[i];
    ll mid=(tree[i].lc+tree[i].rc)/2;
    if(r<=mid)
        kk=query(i*2,l,r);
    else if(l>mid)
        kk=query(i*2+1,l,r);
    else
        kk=getmax(query(i*2,l,mid),query(i*2+1,mid+1,r));
    return kk;
}
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        ll n,m;scanf("%I64d%I64d",&n,&m);
        for(ll i=1;i<=n;i++) scanf("%I64d",&num[i]);
        build(1,1,n);
        while(m--)
        {
            int ch;ll b,c;scanf("%d%I64d%I64d",&ch,&b,&c);
            if(ch==1)
                update(b,c,1);
            else if(ch==0)
            {
                s ans=query(1,b,c);
                printf("%I64d\n",max(max(ans.jj,ans.jo),max(ans.oj,ans.oo)));
            }
        }
    }
    return 0;
}