ST table and tree array

ST table 

 The st table can solve the problem of the most value of the interval. It can do O(nlogn) preprocessing and O(1) query, but does not support modification.

  The general idea of ​​the st table is to use st[i][j] to represent the maximum value in the 2-to-j tree starting from i. When querying, start from the left endpoint to find the length of the interval to the power of 2. Then make a query. However, it is obvious that the length of the interval we want to query is not necessarily a power of 2. Then how to achieve O(1) query, which requires the use of the most valuable features.

 

As shown in the figure, if we want to query the maximum value between 2 and 7, but 7-2+1 is between 2 2 and 2 3 , we choose 2 2 , which is st[2][2], then the rest What to do with 6,7, we consider counting backward from 7, that is, take max as the maximum value from 2 to 7 in st[7-2 2 ​​][2] and st[2][2].

  First, perform preprocessing, st[i][j] represents the j-th power of 2 starting from i, then st[i][j] should be the j-1 power of 2 starting from i and starting from i+2 The maximum value in the j -1 power of 2 starting from j-1, then recursion is fine.

Code:

 

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 const int N=100100;
 5 int n,m,a[N],st[N][20],log[N],cf[20];
 6 void pre()
 7 {
 8   log[2]=1;
 9   log[1]=0;
10   for(int i=3;i<=n;++i)
11   {
12     log[i]=log[i/2]+1;
13   }
14   cf[0]=1;
15   cf[1]=2;
16   for(int i=2;i<=log[n]+1;++i)
17   {
18     cf[i]=cf[i-1]*2;
19   }
20 }
21 int read()
22 {
23   int x=0,f=1;char c=getchar();
24   while(c<'0'||c>'9')
25   {
26     if(c=='-') f=-1;
27     c=getchar();
28   }
29   while(c>='0'&&c<='9')
30   {
31     x=x*10+c-'0';
32     c=getchar();
33   }
34   return x;
35 }
36 int ff(int x,int y)
37 {
38   int l=y-x+1,k=log[l];
39   int f=max(st[x][k],st[y-cf[k]+1][k]);
40   return f;
41 }
42 int main()
43 {
44   n=read(),m=read();
45   pre();
46   for(int i=1;i<=n;++i)
47   {
48     st[i][0]=a[i]=read();
49 
50   }
51 
52   for(int j=1;j<=log[n];++j)
53   {
54     for(int i=1;i+cf[j]-1<=n;++i)
55     {
56       st[i][j]=max(st[i][j-1],st[i+cf[j-1]][j-1]);
57     }
58   }
59   for(int i=1,x,y;i<=m;++i)
60   {
61     x=read(),y=read();
62     cout<<ff(x,y)<<"\n";
63   }
64   return 0;
65 }

 

 

 

 tree array

In fact, I don't really understand the principle of tree array, but because of its short and concise code, I like it very much. . . .

So just post it on the blog by the way. After a while, I really understand the principle and come back to revise it.

Tree-like arrays do not need preprocessing, only two operations: modification and query. The modification can be to add or subtract a value, and the query is a range sum.

First we need two arrays, one is the original array a and the other is the tree array tree.

Then there is the modification, just write a sub-function of a few lines, and then pass the subscript of the modified element and the element to be added into the function, and then a miracle happens.

The query passes in the subscript to be queried to query the interval sum from 1 to the element. If the query is from l to r, you only need to find the interval sum from and to them respectively, and then subtract them, similar to in prefix sum. The specifics are in the code.

Oh, by the way, the tree array seems to also support interval modification and single-point query. I will also wait until I know it and come back to modify it. . . . . .

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 const int N=500005;
 5 int tree[N],n,m;
 6 void add(int a,int pos)
 7 {
 8     while(pos<=n){
 9         tree[pos]+=a;
10         pos+=pos&-pos;
11     }
12 }
13 int cc(int pos)
14 {
15     int ans=0;
16     while(pos>=1){
17         ans+=tree[pos];
18         pos-=pos&-pos;
19     }
20     return ans;
21 }
22 int main()
23 {
24     scanf("%d%d",&n,&m);
25     for(int i=1,x;i<=n;++i)
26     {
27         scanf("%d",&x);
28         add(x,i);
29     }
30     for(int i=1,bz,x,y;i<=m;++i){
31         scanf("%d%d%d",&bz,&x,&y);
32         if(bz==1)
33             add(y,x);
34         else{
35             int kk=cc(y),zz=cc(x-1);
36             printf("%d\n",kk-zz);
37         }
38     }
39     return 0;
40 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325326385&siteId=291194637