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
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]
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