HDU 1166 线段树的区间查询和单点更新

之前在学习线段树,怎么看都不懂,但是每次看都能明白那么一点,后来看了一片博客,一位大神的随笔,看了一个上午终于理解了线段树

po出博客地址,刚入门的同学可以好好看一看,会有一些收获https://www.cnblogs.com/TheRoadToTheGold/p/6254255.html

这道题标准的模版题,单点更新,并不涉及lazy操作。

# include <iostream>
# include <string>
using namespace std;
const int N=5*1e5+5;
int ans=0;
struct node
{
    int left,right;
    int val;
    int lazy;
    int mid()
    { 
        return (left+right)/2; 
    }
} tree[4*N];
inline void build(int rt,int l,int r)
{
    tree[rt].left=l;
    tree[rt].right=r;
    if(l==r)
    {
        std::ios::sync_with_stdio(false);
        cin>>tree[rt].val;
        return ;
    }
    build(rt<<1,l,(l+r)/2);
    build(rt<<1|1,(l+r)/2+1,r);
    tree[rt].val=tree[rt<<1].val + tree[rt<<1|1].val;
}
inline void push_down(int rt)
{
    tree[rt<<1].lazy+=tree[rt].lazy;
    tree[rt<<1|1].lazy+=tree[rt].lazy;
    tree[rt<<1].val+=tree[rt].lazy*(tree[rt<<1].right - tree[rt<<1].left +1);
    tree[rt<<1|1].val+=tree[rt].lazy*(tree[rt<<1|1].right - tree[rt<<1|1].right +1);
    tree[rt].lazy=0;
}

inline void update(int rt,int pos,int num)
{
    if(tree[rt].left == tree[rt].right)
    {
    //    tree[rt].lazy+=num;
        tree[rt].val+=num;
        return ;
    }
///    if(tree[rt].lazy)
//    push_down(rt);
    int mid=tree[rt].mid();
    if(pos<=mid)
    update(rt<<1,pos,num);
    else
    update(rt<<1|1,pos,num);
    tree[rt].val=tree[rt<<1].val + tree[rt<<1|1].val;
}

inline void query(int rt,int x,int y) 
{
    if(tree[rt].left>=x && tree[rt].right<=y)
    {
        ans+=tree[rt].val;
        return ;
    }
//    if(tree[rt].lazy)
//    push_down(rt);
    int mid=tree[rt].mid();
    if(x<=mid)
    query(rt<<1,x,y);
    if(y>mid)
    query(rt<<1|1,x,y);
}
int main()
{
    int t;
    std::ios::sync_with_stdio(false);
    cin>>t;
    string str;
    for(int k=1;k<=t;k++)
    {
        int n;
        cin>>n;
        int x,y;
        build(1,1,n);
        cout<<"Case "<<k<<":"<<endl;
        while(cin>>str)
        {
            if(str[0]=='E')
            break;
            else
            {
            cin>>x>>y;
            if(str[0]=='Q')
            {
                ans=0;
                query(1,x,y);
                cout<<ans<<endl;
            }
            else
            if(str[0]=='A')
            {
                
                update(1,x,y);
            }
            else
            {
                update(1,x,-y);
            }
            }
        }
    }
    return 0;
}
其实这道题卡在时间上了,不建议写我这种update函数,毕竟只是单点更新,可以设置一个数组记录每个叶子节点的位置,直接自底向上的更新会更节省时间,
而这种自顶向下的更新更适合区间更新(+lazy操作)。
posted @ 2018-09-07 16:39  奥义千年杀  阅读(119)  评论(0)    收藏  举报