线段树
参考资料:http://www.notonlysuccess.com/index.php/segment-tree-complete/
hdu1166
题意:对于n(n≤500000),操作有两种:①任意更改某个点的值②求任意区间的和
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 const int N=50005<<2; 3 int sum[N]; 4 int T,n; 5 ///rt表示当前子树的根(root),也就是当前所在的结点 6 void PushUP(int rt){ 7 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 8 } 9 void build(int left,int right,int rt){ 10 if(left==right) { 11 scanf("%d",&sum[rt]); 12 return ; 13 } 14 int mid=(left+right)>>1; 15 build(left,mid,rt<<1); 16 build(mid+1,right,rt<<1|1); 17 PushUP(rt); 18 } 19 void update(int p,int add,int left,int right,int rt){ 20 if(left==right) { 21 sum[rt]+=add; 22 return ; 23 } 24 int mid=(left+right)>>1; 25 if(p<=mid) update(p,add,left,mid,rt<<1); 26 else update(p,add,mid+1,right,rt<<1|1); 27 PushUP(rt); 28 } 29 int query(int L,int R,int left,int right,int rt){ 30 if(L<=left&&right<=R){ 31 return sum[rt]; 32 } 33 int mid=(left+right)>>1; 34 int ret=0; 35 if(L<=mid) ret+=query(L,R,left,mid,rt<<1); 36 if(R>mid) ret+=query(L,R,mid+1,right,rt<<1|1); 37 return ret; 38 } 39 int main(){ 40 int i,j,cas=1; 41 char ch[10]; 42 while(scanf("%d",&T)!=EOF) 43 while(T--){ 44 scanf("%d",&n); 45 build(1,n,1); 46 printf("Case %d:\n",cas++); 47 while(scanf("%s",ch)){ 48 if(ch[0]=='E') break; 49 scanf("%d%d",&i,&j); 50 if(ch[0]=='Q') printf("%d\n",query(i,j,1,n,1)); 51 else if(ch[0]=='S') update(i,-j,1,n,1); 52 else update(i,j,1,n,1); 53 } 54 } 55 return 0; 56 }
hdu1754
题意:区间求最值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 const int N=200005<<2; 3 int Max[N]; 4 int q,n; 5 ///rt表示当前子树的根(root),也就是当前所在的结点 6 int max(int a,int b){return a>b?a:b;} 7 void PushUP(int rt){ 8 Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); 9 } 10 void build(int left,int right,int rt){ 11 if(left==right) { 12 scanf("%d",&Max[rt]); 13 return ; 14 } 15 int mid=(left+right)>>1; 16 build(left,mid,rt<<1); 17 build(mid+1,right,rt<<1|1); 18 PushUP(rt); 19 } 20 void update(int p,int sc,int left,int right,int rt){ 21 if(left==right) { 22 Max[rt]=sc; 23 return ; 24 } 25 int mid=(left+right)>>1; 26 if(p<=mid) update(p,sc,left,mid,rt<<1); 27 else update(p,sc,mid+1,right,rt<<1|1); 28 PushUP(rt); 29 } 30 int query(int L,int R,int left,int right,int rt){ 31 if(L<=left&&right<=R){ 32 return Max[rt]; 33 } 34 int mid=(left+right)>>1; 35 int ret=0; 36 if(L<=mid) ret=max(ret,query(L,R,left,mid,rt<<1)); 37 if(R>mid) ret=max(ret,query(L,R,mid+1,right,rt<<1|1)); 38 return ret; 39 } 40 int main(){ 41 int i,j; 42 char ch[10]; 43 while(scanf("%d%d",&n,&q)!=EOF){ 44 build(1,n,1); 45 while(q--){ 46 scanf("%s",ch); 47 scanf("%d%d",&i,&j); 48 if(ch[0]=='Q') printf("%d\n",query(i,j,1,n,1)); 49 else update(i,j,1,n,1); 50 } 51 } 52 return 0; 53 }
hrbustoj1752
题意:求最值,输出下角标
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 const int N=100005<<2; 3 struct T{ 4 int idx; 5 int Max; 6 }t[N]; 7 int q,n; 8 ///rt表示当前子树的根(root),也就是当前所在的结点 9 T max(T t1,T t2){ 10 if(t1.Max!=t2.Max) return t1.Max>t2.Max?t1:t2; 11 else return t1.idx>t2.idx?t1:t2; 12 } 13 void PushUP(int rt){ 14 t[rt]=max(t[rt<<1],t[rt<<1|1]); 15 } 16 void build(int left,int right,int rt){ 17 if(left==right) { 18 scanf("%d",&t[rt].Max); 19 t[rt].idx=left; 20 return ; 21 } 22 int mid=(left+right)>>1; 23 build(left,mid,rt<<1); 24 build(mid+1,right,rt<<1|1); 25 PushUP(rt); 26 } 27 void update(int p,int sc,int left,int right,int rt){ 28 if(left==right) { 29 t[rt].Max=sc; 30 return ; 31 } 32 int mid=(left+right)>>1; 33 if(p<=mid) update(p,sc,left,mid,rt<<1); 34 else update(p,sc,mid+1,right,rt<<1|1); 35 PushUP(rt); 36 } 37 T query(int L,int R,int left,int right,int rt){ 38 if(L<=left&&right<=R){ 39 return t[rt]; 40 } 41 int mid=(left+right)>>1; 42 T ret;ret.Max=0; 43 if(L<=mid) ret=max(ret,query(L,R,left,mid,rt<<1)); 44 if(R>mid) ret=max(ret,query(L,R,mid+1,right,rt<<1|1)); 45 return ret; 46 } 47 int main(){ 48 int i,j; 49 char ch[10]; 50 while(scanf("%d",&n)!=EOF){ 51 build(1,n,1); 52 scanf("%d",&q); 53 while(q--){ 54 scanf("%s",ch); 55 if(ch[0]=='Q') { 56 T tmp=query(1,n,1,n,1); 57 printf("%d %d\n",tmp.idx,tmp.Max); 58 } 59 else { 60 scanf("%d%d",&i,&j); 61 update(i,j,1,n,1); 62 } 63 } 64 puts(""); 65 } 66 return 0; 67 }
这道题或者用堆,或者用优先队列
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <queue> 3 #include <iostream> 4 using namespace std; 5 struct info{ 6 int idx; 7 int key; 8 bool operator < (const info &a) const { 9 if(a.key!=key) return a.key>key; 10 else return a.idx>idx; 11 } 12 }; 13 int f[100005]; 14 int main(){ 15 int n,q; 16 int i,j,k; 17 info now; 18 char ch; 19 while(scanf("%d",&n)!=EOF){ 20 priority_queue<info>pq; 21 for(i=1;i<=n;++i){ 22 scanf("%d",&f[i]); 23 now.idx=i; 24 now.key=f[i]; 25 pq.push(now); 26 } 27 scanf("%d",&q); 28 while(q--){ 29 getchar(); 30 scanf("%c",&ch); 31 if(ch=='Q') { 32 while(f[pq.top().idx]!=pq.top().key){ 33 pq.pop(); 34 } 35 printf("%d %d\n",pq.top().idx,pq.top().key); 36 } 37 else{ 38 scanf("%d %d",&i,&j); 39 f[i]=j; 40 now.idx=i; 41 now.key=j; 42 pq.push(now); 43 } 44 } 45 puts(""); 46 } 47 return 0; 48 }