线段树专题之单点更新(最基础的线段树,只更新叶子节点,然后把信息更新)
HDU1166(区间求和)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166
#include<iostream> #include<cstdio> #include<cstring> #define lson l,m,rt<<1 //定义左儿子 #define rson m+1,r,rt<<1|1 //定义右儿子 using namespace std; const int maxn=50001; int sum[maxn<<2]; void pushUP(int rt) //更新到父结点 { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l,int r,int rt) //建立树 { if(l==r) { scanf("%d",&sum[rt]); return; } int m=(l+r)>>1; build(lson); build(rson); pushUP(rt); } void update(int p,int add,int l,int r,int rt) //单点增减 { if(l==r) { sum[rt]+=add; return; } int m=(l+r)>>1; if(p<=m) update(p,add,lson); else update(p,add,rson); pushUP(rt); } int query(int L,int R,int l,int r,int rt) //区间求和 { if(L<=l&&r<=R) return sum[rt]; int m=(l+r)>>1; int ret=0; if(L<=m) ret+=query(L,R,lson); if(R>m) ret+=query(L,R,rson); return ret; } int main() { int T,n; scanf("%d",&T); for(int cas=1;cas<=T;cas++) { printf("Case %d:\n",cas); scanf("%d",&n); build(1,n,1); char op[10]; while(scanf("%s",op)) { if(op[0]=='E') break; int a,b; scanf("%d%d",&a,&b); if(op[0]=='Q') printf("%d\n",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; }
HDU 1754(区间最大值)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754
本人AC的第一道线段树,纪念一下,下面贴解题代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int maxn=200001; int sum[maxn<<2]; void pushUP(int rt) { sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); } void build(int l,int r,int rt) { if(l==r) { scanf("%d",&sum[rt]); return; } int m=(l+r)/2; build(lson); build(rson); pushUP(rt); } void update(int p,int s,int l,int r,int rt) { if(l==r) { sum[rt]=s; return; } int m=(l+r)/2; if(p<=m) update(p,s,lson); else update(p,s,rson); pushUP(rt); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) return sum[rt]; int m=(l+r)/2; int ret=0; if(L<=m) ret=max(ret,query(L,R,lson)); if(R>m) ret=max(ret,query(L,R,rson)); return ret; } int main() { int n,m; while(cin>>n>>m) { build(1,n,1); while(m--) { char op[2]; int a,b; scanf("%s%d%d",op,&a,&b); if(op[0]=='Q') printf("%d\n",query(a,b,1,n,1)); else update(a,b,1,n,1); } } return 0; }
HDU1394(求最小逆序数)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394
思路:对于一个数x[i],将其移至最后其逆序数的数量相当于减去比x[i]小的数再加上比x[i]大的数
#include<iostream> #include<cstdio> #include<cstring> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int maxn=5001; int sum[maxn<<2]; void pushUP(int rt) //更新父节点 { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l,int r,int rt) //建树 { sum[rt]=0; if(l==r) return; int m=(l+r)/2; build(lson); build(rson); } void update(int p,int l,int r,int rt) //单点增减 { if(l==r) { sum[rt]++; return; } int m=(l+r)/2; if(p<=m) update(p,lson); else update(p,rson); pushUP(rt); } int query(int L,int R,int l,int r,int rt) //区间求和 { if(L<=l&&r<=R) return sum[rt]; int m=(l+r)/2; int ret=0; if(L<=m) ret+=query(L,R,lson); if(R>m) ret+=query(L,R,rson); return ret; } int x[maxn]; int main() { int n; while(cin>>n) { build(0,n-1,1); int sum=0; for(int i=0;i<n;i++) { scanf("%d",&x[i]); sum+=query(x[i],n-1,0,n-1,1); update(x[i],0,n-1,1); } int ret=sum; for(int i=0;i<n;i++) //将x[i]移至尾部的其值为减去比x[i]小的,加上比x[i]大的 { sum+=n-1-x[i]-x[i]; ret=min(ret,sum); } cout<<ret<<endl; } return 0; }
HDU2795
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795
题解:每次找到最大值的位子,然后减去L
线段树功能:query:区间求最大值的位子(直接把update的操作在query里做了)
#include <cstdio> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 222222; int h , w , n; int MAX[maxn<<2]; void PushUP(int rt) { MAX[rt] = max(MAX[rt<<1] , MAX[rt<<1|1]); } void build(int l,int r,int rt) { MAX[rt] = w; if (l == r) return ; int m = (l + r) >> 1; build(lson); build(rson); } int query(int x,int l,int r,int rt) { if (l == r) { MAX[rt] -= x; return l; } int m = (l + r) >> 1; int ret = (MAX[rt<<1] >= x) ? query(x , lson) : query(x , rson); PushUP(rt); 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\n",query(x , 1 , h , 1)); } } return 0; }