码迷,mamicode.com
首页 > 其他好文 > 详细

HDU-1166 炮兵布阵 (简单线段树)

时间:2019-07-24 11:48:55      阅读:104      评论:0      收藏:0      [点我收藏+]

标签:完整   --   signed   ace   思路   个数   down   case   span   

题意:给N个数,然后给出N个数对应的数值,然后对叶子结点进行add,sub,query操作 输入end时即寻问结束

思路:对于RMQ问题当然使用线段树比较方便,同时这道题也是最简单的线段树(因为只对叶子结点进行修改,而没有对区间进行修改)对结点进行sub(减)操作即使 加入一个相反数

 

完整题解:

 

 

 

别人的模板修改:(这个有区间修改)

#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
const int MAXN = 5e5+1;
unsigned ll n,m,a[MAXN],ans[MAXN<<2],tag[MAXN<<2];
inline ll ls(ll x)
{
    return x<<1;
}
inline ll rs(ll x)
{
    return x<<1|1;
}
void scan()
{
    cin>>n;//1 
    for(ll i=1;i<=n;i++)
    scanf("%lld",&a[i]);
}
inline void push_up(ll p)
{
    ans[p]=ans[ls(p)]+ans[rs(p)];
}
void build(ll p,ll l,ll r)
{
    tag[p]=0;
    if(l==r){ans[p]=a[l];return ;}
    ll mid=(l+r)>>1;
    build(ls(p),l,mid);
    build(rs(p),mid+1,r);
    push_up(p);
} 
inline void f(ll p,ll l,ll r,ll k)
{
    tag[p]=tag[p]+k;
    ans[p]=ans[p]+k*(r-l+1);
}
inline void push_down(ll p,ll l,ll r)
{
    ll mid=(l+r)>>1;
    f(ls(p),l,mid,tag[p]);
    f(rs(p),mid+1,r,tag[p]);
    tag[p]=0;
}
inline void update(ll nl,ll nr,ll l,ll r,ll p,ll k)
{
    if(nl<=l&&r<=nr)
    {
        ans[p]+=k*(r-l+1);
        tag[p]+=k;
        return ;
    }
    push_down(p,l,r);
    ll mid=(l+r)>>1;
    if(nl<=mid)update(nl,nr,l,mid,ls(p),k);
    if(nr>mid) update(nl,nr,mid+1,r,rs(p),k);
    push_up(p);
}
ll query(ll q_x,ll q_y,ll l,ll r,ll p)
{
    ll res=0;
    if(q_x<=l&&r<=q_y)return ans[p];
    ll mid=(l+r)>>1;
    push_down(p,l,r);
    if(q_x<=mid)res+=query(q_x,q_y,l,mid,ls(p));
    if(q_y>mid) res+=query(q_x,q_y,mid+1,r,rs(p));
    return res;
}
int main(){
    int T;
    int cnt =0;
    scanf("%d",&T);
    while(T--){
        ll a1,b,c,d,e,f;
        scan();
        build(1,1,n);
        string s; 
        cout<<"Case "<<++cnt<<":"<<endl;
        while(cin>>s){
            if(s=="End") break;
            else {
                if(s=="Query"){
                       scanf("%lld%lld",&e,&f);
                    printf("%lld\n",query(e,f,1,n,1));
                }else if(s=="Add"){
                    scanf("%lld%lld",&b,&d);//1 x y k 含义:将区间[x,y]内每个数加上k
                    update(b,b,1,n,1,d);
                }else{
                    scanf("%lld%lld",&b,&d);//区间减法相当于加法的相反数 
                    update(b,b,1,n,1,-d);
                }    
            } 
        } 
    }
}

 

HDU-1166 炮兵布阵 (简单线段树)

标签:完整   --   signed   ace   思路   个数   down   case   span   

原文地址:https://www.cnblogs.com/Tianwell/p/11236892.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!