1. 程式人生 > >BZOJ4491: 我也不知道題目名字是什麽

BZOJ4491: 我也不知道題目名字是什麽

每次 pos tput 傳送門 clas span style fin 數組

[Submit][Status][Discuss]

Description

給定一個序列A[i],每次詢問l,r,求[l,r]內最長子串,使得該子串為不上升子串或不下降子串

Input

第一行n,表示A數組有多少元素 接下來一行為n個整數A[i] 接下來一個整數Q,表示詢問數量 接下來Q行,每行2個整數l,r N,Q<=50000

Output

對於每個詢問,求[l,r]內最長子串,使得該子串為不上升子串或不下降子串

Sample Input

9
1 2 3 4 5 6 5 4 3
5
1 6
1 7
2 7
1 9
5 9

Sample Output

6
6
5
6
4
//樣例解釋
五個詢問分別對應
[1,6][1,6][2,6][1,6][6,9]
題目傳送門 停課之後有點萎靡。。。 一眼線段樹,據說這是個經典問題??
我覺得我的碼力還可以啊 有一個小細節:記得要把0算兩種情況 代碼如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,Q;
int a[510000]; struct trnode{ int l,r,lc,rc,c;//c表示這個l~r中最長的不上升或不下降 int lm,rm;int la,ra;//lm從左開始的不上升,la從左開始的不下降 }tr[2100000];int trlen; void bt(int l,int r) { int now=++trlen; tr[now].l=l;tr[now].r=r;tr[now].c=0; tr[now].lc=tr[now].rc=-1; tr[now].lm=tr[now].rm=tr[now].la=tr[now].ra=0
; if(l==r) { if(a[l]<=0)tr[now].rm=tr[now].lm=1; if(a[l]>=0)tr[now].la=tr[now].ra=1; tr[now].c=1; } else if(l<r) { int mid=(l+r)/2; tr[now].lc=trlen+1;bt(l,mid); tr[now].rc=trlen+1;bt(mid+1,r); int lc=tr[now].lc,rc=tr[now].rc; tr[now].lm=tr[lc].lm; if(tr[lc].lm==tr[lc].r-tr[lc].l+1)tr[now].lm+=tr[rc].lm; tr[now].la=tr[lc].la; if(tr[lc].la==tr[lc].r-tr[lc].l+1)tr[now].la+=tr[rc].la; tr[now].rm=tr[rc].rm; if(tr[rc].rm==tr[rc].r-tr[rc].l+1)tr[now].rm+=tr[lc].rm; tr[now].ra=tr[rc].ra; if(tr[rc].ra==tr[rc].r-tr[rc].l+1)tr[now].ra+=tr[lc].ra; int minx,maxx; minx=max( max(tr[now].lm,tr[lc].c),max(tr[now].rm,tr[lc].rm+tr[rc].lm) ); maxx=max( max(tr[rc].c,tr[now].la),max(tr[now].ra,tr[lc].ra+tr[rc].la) ); tr[now].c=max( minx , maxx ); } } int findmax(int now,int l,int r) { if(tr[now].l==l&&tr[now].r==r)return tr[now].c; int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; if(mid+1<=l)return findmax(rc,l,r); else if(r<=mid)return findmax(lc,l,r); else { int lx=findmax(lc,l,mid),rx=findmax(rc,mid+1,r); int jiehe_max=min(tr[lc].r-l+1,tr[lc].ra)+min(r-tr[rc].l+1,tr[rc].la); int jiehe_min=min(tr[lc].r-l+1,tr[lc].rm)+min(r-tr[rc].l+1,tr[rc].lm); return max(max(jiehe_max,jiehe_min),max(lx,rx)); } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<n;i++)a[i]=a[i+1]-a[i]; trlen=0;bt(1,n-1); scanf("%d",&Q); while(Q--) { int l,r; scanf("%d%d",&l,&r); if(l==r){printf("1\n");continue;} if(l>r)swap(l,r); r--; printf("%d\n",findmax(1,l,r)+1); } return 0; }

by_lmy

BZOJ4491: 我也不知道題目名字是什麽