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操作)。

浙公网安备 33010602011771号