单点更新:最基础的线段树,只更新叶子结点,然后用PushUp函数将信息更新上来。
HDU1166 敌兵布阵
线段树功能:update单点增减,query区间求和。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define lson l, mid, root << 1 #define rson mid + 1, r, root << 1 | 1 const int maxn = 50005; int sum[maxn << 2]; int t,n; char op[10]; void PushUp(int root){ sum[root] = sum[root << 1] + sum[root << 1 | 1]; } void build(int l,int r,int root) { if(l == r){ scanf("%d",&sum[root]); return; } int mid = (l + r) >> 1; build(lson);build(rson); PushUp(root); } void update(int pos,int add,int l,int r,int root) { if(l == r){ sum[root] += add; return; } int mid = (l + r) >> 1; if(pos <= mid) update(pos,add,lson); else update(pos,add,rson); PushUp(root); } int query(int L,int R,int l,int r,int root) { if(L <= l && r <= R){ return sum[root]; } int mid = (l + r) >> 1; int ret = 0; if(L <= mid) ret += query(L,R,lson); if(R > mid) ret += query(L,R,rson); return ret; } int main() { scanf("%d",&t); for(int cas = 1; cas <= t; cas++) { scanf("%d",&n); build(1,n,1); printf("Case %d: ",cas); while(~scanf("%s",op)) { if(op[0] == 'E') break; int a,b; scanf("%d%d",&a,&b); if(op[0] == 'Q'){ printf("%d ",query(a,b,1,n,1)); } else if(op[0] == 'S'){ update(a,-b,1,n,1); } else{ update(a,b,1,n,1); } } } return 0; }
HDU1754 I Hate It
线段树功能:update单点替换,query区间最值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define lson l, mid, root << 1 #define rson mid + 1, r, root << 1 | 1 const int maxn = 200005; int MAX[maxn << 2]; int n,m,a,b; char op[5]; void PushUp(int root){ MAX[root] = max(MAX[root <<1],MAX[root << 1 | 1]); } void build(int l,int r,int root) { if(l == r){ scanf("%d",&MAX[root]); return; } int mid = (l + r) >> 1; build(lson);build(rson); PushUp(root); } void update(int pos,int src,int l,int r,int root) { if(l == r){ MAX[root] = src; return; } int mid = (l + r) >> 1; if(pos <= mid) update(pos,src,lson); else update(pos,src,rson); PushUp(root); } int query(int L,int R,int l,int r,int root) { if(L <= l && r <= R){ return MAX[root]; } int mid = (l + r) >> 1; int ret = 0; if(L <= mid) ret = max(ret,query(L,R,lson)); if(R > mid) ret = max(ret,query(L,R,rson)); return ret; } int main() { while(~scanf("%d%d",&n,&m)) { build(1,n,1); while(m--) { scanf("%s%d%d",op,&a,&b); if(op[0] == 'Q'){ printf("%d ",query(a,b,1,n,1)); } else{ update(a,b,1,n,1); } } } return 0; }
HDU1394 Minimum Inversion Number
题意:一个由0...n-1组成的序列,每次将队首的元素移到队尾,求形成的n个序列中最小逆序对数目。
思路:O(nlogn)复杂度求出最初的逆序对数后,O(1)地推出其他序列的逆序对数。
线段树功能:update单点增减,query区间求和。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define lson l, mid, root << 1 #define rson mid + 1, r, root << 1 | 1 const int maxn = 5005; int sum[maxn << 2],x[maxn]; int n,ans,res; void PushUp(int root){ sum[root] = sum[root << 1] + sum[root << 1 | 1]; } void build(int l,int r,int root) { sum[root] = 0; if(l == r)return; int mid = (l + r) >> 1; build(lson);build(rson); } void update(int pos,int l,int r,int root) { if(l == r){ sum[root]++; return; } int mid = (l + r) >> 1; if(pos <= mid) update(pos,lson); else update(pos,rson); PushUp(root); } int query(int L,int R,int l,int r,int root) { if(L <= l && r <= R){ return sum[root]; } int mid = (l + r) >> 1; int ret = 0; if(L <= mid) ret += query(L,R,lson); if(R >= mid) ret += query(L,R,rson); return ret; } int main() { while(~scanf("%d",&n)) { build(0,n-1,1); ans = 0; for(int i=0;i<n;i++){ scanf("%d",&x[i]); ans += query(x[i],n-1,0,n-1,1); update(x[i],0,n-1,1); } res = ans; for(int i=0;i<n;i++){ ans += n - x[i] - x[i] - 1; res = min(res,ans); } printf("%d ",res); } return 0; }
HDU2795 Billboard
题意:h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子。
思路:求区间最大值,每次找到最大值的位置然后减去L。实际上就是不断的二分区间寻找合法的位置。
线段树功能:query区间最大值的位置,update的操作放在了query里面做。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define lson l, mid, root << 1 #define rson mid + 1, r, root << 1 | 1 const int maxn = 200005; int h,w,n; int MAX[maxn << 2]; void PushUp(int root){ MAX[root] = max(MAX[root << 1],MAX[root << 1 | 1]); } void build(int l,int r,int root) { MAX[root] = w; if(l == r) return; int mid = (l + r) >> 1; build(lson);build(rson); } int query(int x,int l,int r,int root) { if(l == r){ MAX[root] -= x; return l; } int mid = (l + r) >> 1; int ret = MAX[root << 1] >= x ? query(x,lson) : query(x,rson); PushUp(root); return ret; } int main() { while(~scanf("%d%d%d",&h,&w,&n)) { if(h > n) h = n; build(1,h,1); while(n--) { int x;scanf("%d",&x); if(MAX[1] < x) puts("-1"); else printf("%d ",query(x,1,h,1)); } } return 0; }