如题。
当遇到单点更新时,树状数组往往比线段树更实用。
算法:
设原数序列为a[i],最大值为h[i](树状数组)。
1。单点更新:
直接更新a[i],然后再更新h[i]。若h[i]的值有可能改变的,则表示区间一定包含i结点。那么就两层lowbit更新所有可能的h。
单点更新时间复杂度O(logn*logn)
1 void update(int x) 2 { 3 while(x<=n) 4 { 5 h[x]=a[x]; 6 for(int i=1;i<lowbit(x);i<<=1) 7 h[x]=max(h[x],h[x-i]); 8 x+=lowbit(x); 9 } 10 return ; 11 }
2。区间查询最大值:
设要查询的区间为[L,R],那么就从h[R]开始找,要找[L,R]内的所有区间。所以依然是两层lowbit,然后R向前跳直到跳到L前面。
区间查询最大值时间复杂度O(logn*logn)
1 void findans(int begin,int end) 2 { 3 int ans=0; 4 while(end>=begin) 5 { 6 ans=max(ans,h[end]); 7 end--; 8 for(;end-lowbit(end)>=begin;end-=lowbit(end)) 9 ans=max(ans,h[end]); 10 } 11 12 printf("%d\n",ans); 13 return ; 14 }
相关试题:hdu1754(单点修改,区间求最大值)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 const int maxn=300005; 7 int h[maxn],a[maxn]; 8 int n,m; 9 int lowbit(int x) 10 { 11 return x&(-x); 12 } 13 void update(int x) 14 { 15 while(x<=n) 16 { 17 h[x]=a[x]; 18 for(int i=1;i<lowbit(x);i<<=1) 19 h[x]=max(h[x],h[x-i]); 20 x+=lowbit(x); 21 } 22 return ; 23 } 24 void findans(int begin,int end) 25 { 26 int ans=0; 27 while(end>=begin) 28 { 29 ans=max(ans,a[end]); 30 end--; 31 for(;end-lowbit(end)>=begin;end-=lowbit(end)) 32 ans=max(ans,h[end]); 33 } 34 35 printf("%d\n",ans); 36 return ; 37 } 38 int main() 39 { 40 //freopen("in.txt","r",stdin); 41 //freopen("out.txt","w",stdout); 42 while(scanf("%d%d",&n,&m)==2) 43 { 44 memset(h,0,sizeof(h)); 45 for(int i=1;i<=n;i++) 46 { 47 scanf("%d",&a[i]); 48 update(i); 49 } 50 for(int i=1;i<=m;i++) 51 { 52 char c=getchar(); 53 while(c!=‘Q‘&&c!=‘U‘)c=getchar(); 54 if(c==‘U‘)//update 55 { 56 int y,z; 57 scanf("%d%d",&y,&z); 58 a[y]=z; 59 update(y); 60 continue; 61 } 62 if(c==‘Q‘)//findans 63 { 64 int y,z; 65 scanf("%d%d",&y,&z); 66 findans(y,z); 67 continue; 68 } 69 } 70 } 71 72 return 0; 73 }
时间: 2024-10-06 12:15:07