vijos p1659——河蟹王国(线段树)(复习)

描述

河蟹王国有一位河蟹国王,他的名字叫羊驼。河蟹王国富饶安定,人们和谐相处。有一天,羊驼国王心血来潮,想在一部分人中挑出最和谐的人。于是,羊驼国王将他的子民排成了一列(==!!b汗~好长呀)。每个人都有一个初始的和谐值。羊驼国王每次会选择一个区间[L,R],这个区间中和谐值最大的人就是国王选出的人。而且,在某一时间,区间[L',R']里的人会变得熟悉,因此他们每个人的和谐值都会上升一个相同的值C。羊驼国王想知道,对于每一次选择,他选出的最大和谐值是多少。

格式

输入格式

第一行是一个数N(1<=N<=100000),表示人数。

接下来的N行,每行一个数,表示排成的序列第i个人和谐值的初始值。

接下来是一个数M(1<=M<=100000),表示羊驼国王或他的子民有所活动(羊驼国王选择一个区间算一次,某区间里的人增长和谐值算一次)的总次数。

接下来的M行,每行第一个是一个数K,K是1或2,若K=1,接下来有三个数L,R,C,表示区间[L,R]的所有人增加C的和谐值;若K=2,接下来有两个数L,R,表示国王选择了区间[L,R]。

输出格式

每次对于国王选择区间,输出选择区间里的最大和谐值。

样例1

样例输入1

5
1
2
3
4
5
3
2 1 4
1 1 3 3
2 3 5

样例输出1

4
6

限制

每个测试点1s。

提示

保证所有的数以及结果都在longint范围内。

区间更改,区间查询——线段树/树状数组

这里用的线段树,注意结构体中还要有一个add,表示增加量。在更新操作中,注意:当查询到区间匹配时,区间最大值直接加上输入的增量,用add传递下去再pushup。传递add就pushdown。一定要深刻理解up和down的用法。

居然没有区间和,总觉得写起来怪怪的。。。

还发现了一个很诡异的东西,当查询写成int函数时,不会超时。但当写成void函数时要超时4组,加上inline后才不会超时。。。

祝自己NOIP顺利~

#include<bits/stdc++.h>
using namespace std;
#define L(u) (u*2)
#define R(u) (u*2+1)
const int maxn=1000005;
int a[maxn];
struct node{
    int l,r,maxnum,add;
}w[maxn];
int n,m;int ans=0;
inline void pushup(int u)
{
    w[u].maxnum=max(w[L(u)].maxnum,w[R(u)].maxnum);
    return ;
}
inline void pushdown(int u)
{
    w[L(u)].add+=w[u].add;
    w[L(u)].maxnum+=w[u].add;
    w[R(u)].add+=w[u].add;
    w[R(u)].maxnum+=w[u].add;
    w[u].add=0;
    return ;
}
inline void buildtree(int u,int left,int right)
{
    w[u].l=left;w[u].r=right;
    if(left==right)
    {
        w[u].maxnum=a[left];
        return ;
    }
    int mid=(left+right)>>1;
    buildtree(L(u),left,mid);
    buildtree(R(u),mid+1,right);
    pushup(u);
}
inline void findans(int u,int left,int right)
{
    if(w[u].l==left&&w[u].r==right)
    {
        ans=max(ans,w[u].maxnum);
        return ;
    }
    if(w[u].add!=0)pushdown(u);
    int mid=(w[u].l+w[u].r)>>1;
    if(left>=mid+1)
    findans(R(u),left,right);
    else if(right<=mid)
    findans(L(u),left,right);
    else
    {
        findans(L(u),left,mid);
        findans(R(u),mid+1,right);
    }
    return ;
}
inline void update(int u,int left,int right,int val)
{
    if(w[u].l==left&&w[u].r==right)
    {
        w[u].maxnum+=val;
        w[u].add+=val;
        return ;
    }
    if(w[u].add!=0)pushdown(u);
    int mid=(w[u].l+w[u].r)>>1;
    if(left>=mid+1)
    update(R(u),left,right,val);
    else if(right<=mid)
    update(L(u),left,right,val);
    else
    {
        update(L(u),left,mid,val);
        update(R(u),mid+1,right,val);
    }
    pushup(u);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    buildtree(1,1,n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int q;scanf("%d",&q);
        if(q==1)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            update(1,x,y,z);
            continue;
        }
        else
        {
            int x,y;
            scanf("%d%d",&x,&y);
            ans=-100000000;
            findans(1,x,y);
            printf("%d
",ans);
            continue;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/937337156Zhang/p/6071445.html