hdu-6406-dp+ST表 Taotao Picks Apples

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1446    Accepted Submission(s): 449


Problem Description
There is an apple tree in front of Taotao's house. When autumn comes, p). Can you answer all these queries?
 
Input
The first line of input is a single line of integer ), as described in the problem statement.
 
Output
For each query, display the answer in a single line.
 
Sample Input
1 5 3 1 2 3 4 4 1 5 5 5 2 3
 
Sample Output
1 5 3
 
 
  如果能看出将这个序列分成两半之后利用一些预处理依旧能在log时间内得到答案的话就好办了,比赛的时候想了半天最后发现看错题目了,以为每次求一下LIS。。。这个是贪心的上升并非最优的。
  我们提前做个ST表,用于处理区间最大值下标的查询。dp[0][i]表示从第一个元素到第i个元素的步数,dp[1][i]表示从i贪心的往后走的步数,对于每个<p,q> ,分成[1,p],[p,n] , 找到[1,p]之间的最大值下标j ,和[p,n]中大于这个最大值的下标k, 答案就是  dp[0][j]+dp[1][k]。
  
 1 #include <iostream>
 2 #include<cmath>
 3 using namespace std;
 4 int N,a[100100];
 5 int f[100100][20],dp[2][100100];
 6 void init(){
 7     for(int i=1;i<=N;++i)f[i][0]=i;
 8     for(int k=1;(1<<k)<=N;++k){
 9         for(int i=1;i+(1<<k)-1<=N;++i){
10             if(a[f[i][k-1]]>=a[f[i+(1<<(k-1))][k-1]]) f[i][k]=f[i][k-1];
11             else f[i][k]=f[i+(1<<(k-1))][k-1];
12         }
13     }    
14 }
15 int query(int L,int R){
16     if(R<L)return 0;
17     int k=0;
18     while((1<<(k+1))-1<=R-L) k++;
19     if(a[f[L][k]]>=a[f[R-(1<<k)+1][k]]) return f[L][k];
20     else return f[R-(1<<k)+1][k];
21 }
22 int main() {
23     int t,n,m,i,p,q;
24     cin>>t;
25     while(t--){
26         scanf("%d%d",&n,&m);
27         for(i=1;i<=n;++i)scanf("%d",a+i);
28         N=n,init();
29         dp[0][1]=1;
30         int maxn=1;
31         for(i=2;i<=n;++i){
32             if(a[i]>a[maxn]){
33                 dp[0][i]=dp[0][maxn]+1;
34                 maxn=i;
35             }
36             else dp[0][i]=-1;
37         }
38 
39         dp[1][n]=1;
40         for(i=n-1;i>=1;--i){
41             int l=i+1,r=n;
42             while(l<r){
43                 int mid=l+(r-l)/2;
44                 if(a[query(l,mid)]>a[i]) r=mid;
45                 else l=mid+1;
46             }
47             dp[1][i]=a[r]>a[i]?dp[1][l]+1:1;
48         }
49         while(m--){
50             scanf("%d%d",&p,&q);
51             int x=query(1,p-1),xx=a[x],ans=dp[0][x];
52             if(q>a[x]) xx=q,ans++;
53             int l=p+1,r=n;
54             while(l<r){
55                 int mid=l+(r-l)/2;
56                 if(a[query(p+1,mid)]>xx)r=mid;
57                 else l=mid+1;
58             }
59             if(a[l]>xx) ans+=dp[1][l];
60             cout<<ans<<endl;
61         }
62     }
63     return 0;
64 }