HDU 6406 Taotao Picks Apples 线段树维护
题意:给个T,T组数据;
每组给个n,m;n个数,m个操作;
(对序列的操作是,一开始假设你手上东西是-INF,到i=1时拿起1,之后遍历,遇到比手头上的数量大的数时替换(拿到手的算拿走),问最后拿走几个)
每次操作是将p位变为q;问此时序列能拿走几个数;
思路:假设p位变了,不管变大变小,我们都得知道一件事,就是要找到在p之前最长的序列;
因为这个是不变的,可以预处理,所以说我们就在第i位置记录1~i的最大值,和最大取走的数量以及最大数的id,这样就可以知道p-1位置的信息就是1~p-1位置最大的数的信息,O(1)得到;
(如果q比1~p-1最大的数小,那么就将q变为那个最大的数,因为这样我们就可以不用分情况去查询)
之后就是要找到比q大的第一个数,我是用线段树维护的,找比q大的第一个数的位置;找到了之后你就会希望能得到以这个数为起点的最大可取数量,那么我们就要计算出每个位置开始可以得到的最大数量;实现方法就是倒过来遍历那n个数,每次查询i~n里比a[i]大的第一个数的位置cnt,然后假设记录数组为dp,那么就是dp[i]=dp[cnt]+1;没找到的情况就令这个位置为1
以下是代码实现:
1 #include<bits/stdc++.h> 2 #define mid ((node[now].l+node[now].r)>>1) 3 #define Max(a, b) (a>b?a:b) 4 using namespace std; 5 typedef long long ll; 6 const int N=1e5+7, INF=0x3f3f3f3f, mod=998244353; 7 int dp[N]; 8 struct Node{ 9 int num, id, len; 10 }maxn[N]; 11 int sav[N]; 12 struct No{ 13 int ret; 14 struct no{ 15 int l, r, maxn; 16 }node[N<<2]; 17 void build(int L, int R, int now){ 18 node[now].l=L; 19 node[now].r=R; 20 if(L==R) node[now].maxn=sav[L]; 21 else{ 22 build(L, mid, now<<1); 23 build(mid+1, R, now<<1^1); 24 node[now].maxn=Max(node[now<<1].maxn, node[now<<1^1].maxn); 25 } 26 } 27 void querymax(int v, int now, int L, int R){ 28 if(node[now].l==node[now].r){ 29 if(node[now].maxn>v) ret=min(ret, node[now].l); 30 return ; 31 } 32 if(node[now].r<=R&&node[now].l>=L){ 33 if(node[now<<1].maxn>v){ 34 querymax(v, now<<1, L, R); 35 }else{ 36 querymax(v, now<<1^1, L, R); 37 } 38 return ; 39 } 40 if(L<=mid) 41 querymax(v, now<<1, L, R); 42 if(R>mid) 43 querymax(v, now<<1^1, L, R); 44 } 45 }tree; 46 int main( ){ 47 int T, m, n, p, q; 48 register int i, j, k, ans, cnt, sav1; 49 scanf("%d", &T); 50 while(T--){ 51 scanf("%d%d", &n, &m); 52 for(i=1; i<=n; ++i){ 53 scanf("%d", sav+i); 54 if(maxn[i-1].num<sav[i]){ 55 maxn[i].num=sav[i]; 56 maxn[i].id=i; 57 maxn[i].len=maxn[i-1].len+1; 58 }else{ 59 maxn[i]=maxn[i-1]; 60 } 61 dp[i]=0; 62 } 63 tree.build(1, n, 1); 64 for(i=n; i>0; --i){ 65 tree.ret=n+1; 66 tree.querymax(sav[i], 1, i, n); 67 cnt=tree.ret; 68 if(cnt>n) 69 cnt=0; 70 dp[i]=dp[cnt]+1; 71 } 72 while(m--){ 73 sav1=ans=0; 74 scanf("%d%d", &p, &q); 75 if(p==1){ 76 tree.ret=n+1; 77 tree.querymax(q, 1, p+1, n); 78 cnt=tree.ret; 79 if(cnt<=n) printf("%d\n", dp[cnt]+1); 80 else puts("1"); 81 continue; 82 } 83 ans=maxn[p-1].len; 84 if(q>maxn[p-1].num){ 85 ++ans; 86 }else{ 87 q=maxn[p-1].num; 88 } 89 tree.ret=n+1; 90 tree.querymax(q, 1, p+1, n); 91 cnt=tree.ret; 92 if(cnt<=n) 93 ans+=dp[cnt]; 94 printf("%d\n", ans); 95 } 96 } 97 }