多校第8场 hdu6406 Taotao Picks Apples 单调栈+主席树

题目连接:Taotao Picks Apples

题意:给一个数列,然后替换掉一个数,求从左开始的严格递增序列长度(第一个必选)

题解:先预习处理前缀最大值和到这里的长度,在用单调栈处理出从i这里开始的递增序列长度。然后从n~1倒着建立主席树维护区间的最小下标。这样就可以询问后面开始的最小位置,对于每次询问反过来注意一下细节就可以了。

 1 #include<bits/stdc++.h>
 2 #define eps 1e-10;
 3 using namespace std;
 4 const int N = 1e5+7,M=6000005;
 5 
 6 int h[N],n,m;
 7 int mx[N],w[N],len[N];//前缀最大值,1到i递增序列长度,i到n的递增序列长度
 8 int que[N],ed,top,fa[N],pp[N];//队列,栈底,栈顶,fa[i]下一个比i大的位置,pp[i]表示1~i递增序列的最后一个下标
 9 int ls[M],rs[M],mi[M],rt[N],tot,sz;//左右儿子,位置,
10 void init()
11 {
12     tot=ed=top=0;
13 }
14 void update(int &o,int pre,int l,int r,int x,int  p)
15 {
16     o=++tot;ls[o]=ls[pre];rs[o]=rs[pre];
17     mi[o]=min(mi[pre],p);
18     if(l==r)return;
19     int m=(l+r)>>1;
20     if(x<=m) update(ls[o],ls[pre],l,m,x,p);
21     else update(rs[o],rs[pre],m+1,r,x,p);
22 }
23 int query(int rt,int l,int r,int p)
24 {
25     if(!rt||p>r)return n+1;
26     if(p<=l)return mi[rt];
27     int m=(l+r)>>1;
28     if(p<=m)return min(query(ls[rt],l,m,p),query(rs[rt],m+1,r,p));
29     return query(rs[rt],m+1,r,p);
30 }
31 int main(){
32     int T;
33     scanf("%d",&T);
34     while(T--)
35     {
36         init();
37         scanf("%d %d",&n,&m);
38         for(int i=1;i<=n;i++)
39         {
40             scanf("%d",&h[i]);
41         }
42         for(int i=1;i<=n;i++)
43         {
44             if(h[i]>mx[i-1])
45             {
46                 mx[i]=h[i]; w[i]=w[i-1]+1; pp[i]=i;
47             }
48             else
49             {
50                 mx[i]=mx[i-1];w[i]=w[i-1]; pp[i]=pp[i-1];
51             }
52         }
53         for(int i=n;i>=1;i--)
54         {
55             while(top>ed&&h[que[top]]<=h[i])top--;
56             que[++top]=i;
57             len[i]=top-ed;
58              if(top-ed>1)fa[i]=que[top-1];
59             else fa[i]=n+1;
60         }
61         mi[0]=n+1;rt[n+1]=0;len[n+1]=0;
62         for(int i=n;i>=1;i--)
63         {
64             update(rt[i],rt[i+1],1,1e9,h[i],i);
65         }
66         while(m--)
67         {
68             int p,x;
69             scanf("%d %d",&p,&x);
70             if(p==1)
71             {
72                  printf("%d\n",1+len[query(rt[p+1],1,1e9,x+1)]);
73             }
74             else
75             {
76                 int pre=pp[p-1];
77                 if(fa[pre]==p)
78                 {
79                     if(x>h[pre])printf("%d\n",w[p]+len[query(rt[p+1],1,1e9,x+1)]);
80                     else printf("%d\n",w[pre]+len[query(rt[p+1],1,1e9,h[pre]+1)]);
81                 }
82                 else
83                 {
84                     if(x>h[pre])printf("%d\n",1+w[p]+len[query(rt[p+1],1,1e9,x+1)]);
85                     else printf("%d\n",w[n]);
86                 }
87             }
88         }
89     }
90     return 0;
91 }

 

posted @ 2018-08-16 15:44  lhclqslove  阅读(249)  评论(0编辑  收藏  举报