首页 > 代码库 > 2014 summer 知识点总结1之线段树

2014 summer 知识点总结1之线段树

HDU 1166

【题意】:

n个阵营一字排开,每个初始有a[i]个人。现有两种操作:

Q a b 查询[a,b]之间总人数并输出

A/S a b 在a号位添加/删除b个人

【分析】:最基本的单点更新和区间查询,维护节点信息sum[o]

【代码】:

 1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4  5 using namespace std; 6  7 int numv[50005<<2]; 8 int A[50005]; 9 10 void builtTree(int o,int l,int r){11     if(l==r) {12         numv[o]=A[l];13         return ;14     }15     int m=l+(r-l)/2;16     builtTree(2*o,l,m);17     builtTree(2*o+1,m+1,r);18     numv[o]=numv[2*o]+numv[2*o+1];19     return ;20 }21 void Update(int o,int l,int r,int p,int x){22     if(l==r && l==p){23         A[l]=x;24         numv[o]=x;25         return ;26     }27     int m=l+(r-l)/2;28     if (p<=m) Update(2*o,l,m,p,x);29     if (p>=m+1)Update(2*o+1,m+1,r,p,x);30     numv[o]=numv[2*o]+numv[2*o+1];31 }32 int Query(int ql,int qr,int o,int l,int r){33     if (ql<=l && r<=qr) return numv[o];34     int m=l+(r-l)/2;35     int ans=0;36     if (ql<=m) ans+=Query(ql,qr,2*o,l,m);37     if (m+1<=qr) ans+=Query(ql,qr,2*o+1,m+1,r);38     return ans;39 }40 int t,n;41 int main(){42     scanf("%d",&t);43     for(int cas=1;cas<=t;cas++){44         scanf("%d",&n);45         printf("Case %d:\n",cas);46         for(int i=1;i<=n;i++) scanf("%d",&A[i]);47         builtTree(1,1,n);48         char s[105];49         while(~scanf("%s",s)){50             if (s[0]==E) {51                 break;52             }53             int a,b;54             scanf("%d%d",&a,&b);55             if (s[0]==Q){56                 int ans=Query(a,b,1,1,n);57                 printf("%d\n",ans);58             }59             if (s[0]==A){60                 Update(1,1,n,a,A[a]+b);61             }62             if (s[0]==S){63                 Update(1,1,n,a,A[a]-b);64             }65         }66     }67     return 0;68 }
View Code

 

HDU 1754

【题意】:给n个数字。m次操作,每次操作更新一个数字或者查询区间最大值。

【分析】:基本单点更新区间查询,维护节点信息max[o]

【代码】:

 1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #define Mod 1000000007 5 #define LL long long 6 #define toL 2*o,l,m 7 #define toR 2*o+1,m+1,r 8 using namespace std; 9 10 int maxv[200005<<2];11 int A[200005];12 13 void builtTree(int o,int l,int r){14     if (l==r){15         maxv[o]=A[l];16         return ;17     }18     int m=(l+r)/2;19     builtTree(toL);20     builtTree(toR);21     maxv[o]=max(maxv[2*o],maxv[2*o+1]);22     return ;23 }24 void Updata(int o,int l,int r,int p,int x){25     if (l==r && p==l){26         maxv[o]=x;27         return ;28     }else {29         int m=(r+l)/2;30         if (p<=m) Updata(toL,p,x);31         if (m+1<=p) Updata(toR,p,x);32         maxv[o]=max(maxv[2*o],maxv[2*o+1]);33         return ;34     }35 }36 int Query(int o,int l,int r,int ql,int qr){37     if (ql<=l && r<=qr) return maxv[o];38     int m=(r+l)/2;39     int ans=-1;40     if (ql<=m) ans=max(ans,Query(toL,ql,qr));41     if (m+1<=qr) ans=max(ans,Query(toR,ql,qr));42     return ans;43 }44 int n,q;45 46 int main(){47     while(~scanf("%d%d",&n,&q)){48         for(int i=1;i<=n;i++) scanf("%d",&A[i]);49         builtTree(1,1,n);50         for(int i=1;i<=q;i++){51             int a,b;52             char s[3];53             scanf("%s%d%d",s,&a,&b);54             if (s[0]==Q){55                 printf("%d\n",Query(1,1,n,a,b));56             }57             if (s[0]==U){58                 Updata(1,1,n,a,b);59             }60         }61     }62     return 0;63 }
View Code

 

HDU 1394

【题意】:就是给出一串数,当依次在将第一个数变为最后一个数的过程中,要你求它的最小逆序数。

【分析】:每次维护sumv求区间内有多少个数字,处理出LOW[],UP[]后利用sum每次枚举

       for(int i=1;i<=n;i++){            scanf("%d",&A[i]);            A[i]++;        //    cout<<"Q="<<Query(1,1,n,A[i]+1,n)<<endl;            if (A[i]+1<=n) sum+=Query(1,1,n,A[i]+1,n);            updata(1,1,n,A[i],1);//令A【i】的位置为1,那么sunv就相当于一个求和了            A[i]--;//信息已经保存到树中,A[i]可还原        }

【代码】:

 1 /*HDU1394搜索写法*/ 2 #include <iostream> 3 #include <string.h> 4 #include <stdio.h> 5 #define LL 2*o,l,m 6 #define LR 2*o+1,m+1,r 7 using namespace std; 8  9 int A[50005];10 int Low[50005],Up[50005];11 int numv[50005<<2];//[1...50005]有多少个数12 13 int Query(int o,int l,int r,int ql,int qr){14     if (ql<=l && r<=qr) return numv[o];15     int m=(r+l)>>1;16     int ans=0;17     if (ql<=m) ans+=Query(LL,ql,qr);18     if (m+1<=qr) ans+=Query(LR,ql,qr);19     return ans;20 }21 void updata(int o,int l,int r,int p,int x){22    // cout<<"l="<<l<<","<<"r="<<r<<endl;23 24     if (l==r && p==l) {25         numv[o]=1;26         return ;27     }28     int m=(r+l)>>1;29     if (p<=m)updata(LL,p,x);30     if (m+1<=p)updata(LR,p,x);31     numv[o]=numv[2*o]+numv[2*o+1];32     return;33 }34 int main(){35     int n;36     while(~scanf("%d",&n)){37         memset(numv,0,sizeof(numv));38         int ans,sum=0;39         for(int i=1;i<=n;i++){40             scanf("%d",&A[i]);41             A[i]++;42         //    cout<<"Q="<<Query(1,1,n,A[i]+1,n)<<endl;43             if (A[i]+1<=n) sum+=Query(1,1,n,A[i]+1,n);44             updata(1,1,n,A[i],1);//令A【i】的位置为1,那么sunv就相当于一个求和了45             A[i]--;//信息已经保存到树中,A[i]可还原46         }47         ans=sum;48         for(int i=0;i<n;i++){49             Low[i]=i;50             Up[i]=n-i-1;51         }52         for(int i=1;i<=n-1;i++){53             sum=sum+(Up[A[i]]-Low[A[i]]);54             ans=min(sum,ans);55         }56         printf("%d\n",ans);57     }58     return 0;59 }
View Code

 

 

【题意】:

【分析】:

【代码】:

 

 

 

【题意】:

【分析】:

【代码】: