hdu1968 區間更新+區間求和(線段樹)
阿新 • • 發佈:2018-12-24
這次是把某個區間全部更新為一個值,而不是增加或減少。最後詢問一下區間總和。
思路還是差不多的。在更新時,當我們將一個節點所維護的區間更新後,可以用這個區間的長度*新的值,即
tree[x].sum = (tree[x].r-tree[x].l+1)*tree[x].data。
在查詢或更新區間時,可以將tree[x].data作為懶惰標記繼續往下傳,最後完成push_up操作:
tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum;
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> const int maxn = 100000+5; using namespace std; int t,n,q,x,y,z; struct node{ int l,r; int sum,data; void update(int x) { data = x; } }tree[maxn*4]; void getsum(int x) { tree[x].sum = (tree[x].r-tree[x].l+1)*tree[x].data; } void push_down(int x) { int lazyval = tree[x].data; if(lazyval) { tree[x<<1].update(lazyval); getsum(x<<1); tree[x<<1|1].update(lazyval); getsum(x<<1|1); tree[x].data = 0; } } void build(int x,int l,int r) { tree[x].l = l,tree[x].r = r; if(l==r){ tree[x].sum = 1; tree[x].data = 1; } else{ int mid = (l+r)/2; build(x<<1,l,mid); build(x<<1|1,mid+1,r); tree[x].data = 0; tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum; } } void update(int x,int l,int r,int z) { int L=tree[x].l,R=tree[x].r; if(l<=L&&r>=R) { tree[x].data = z; getsum(x); } else{ push_down(x); int mid = (L+R)/2; if(l<=mid) update(x<<1,l,r,z); if(r>mid) update(x<<1|1,l,r,z); tree[x].sum = tree[x<<1].sum+tree[x<<1|1].sum; } } long long query(int x,int l,int r) { int L=tree[x].l,R=tree[x].r; long long ans = 0; if(l<=L&&r>=R) ans += tree[x].sum; else{ push_down(x); int mid = (L+R)/2; if(l<=mid) ans+=query(x<<1,l,r); if(r>mid) ans+=query(x<<1|1,l,r); getsum(x); //cout<<ans<<endl; } return ans; } int main() { freopen("d://test.txt","r",stdin); scanf("%d", &t); for(int j=1;j<=t;j++) { scanf("%d", &n); build(1,1,n); scanf("%d",&q); for(int i=0;i<q;i++) { scanf("%d%d%d",&x,&y,&z); update(1,x,y,z); } // for(int i=1;i<=n;i++) // cout<<tree[i].sum<<endl; printf("Case %d: The total value of the hook is %d.\n",j,tree[1].sum); } return 0; }