日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

BZOJ4491: 我也不知道题目名字是什么

發布時間:2023/11/27 生活经验 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ4491: 我也不知道题目名字是什么 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【傳送門:BZOJ4491】


簡要題意:

  給出一個長度為n的序列,m個操作,每個操作輸入x,y,求出第x個數到第y個數的最長子串,保證這個最長子串是不上升或不下降子串


題解:

  線段樹

  因為不上升或不下降嘛,就差分一下唄

  每一段區間維護:

  d表示最多連續的非正數的個數,u表示最多連續的非負數的個數

  ld表示左端點開始向右連續的非正數的個數,rd表示右端點開始向左連續的非正數的個數

  lu表示左端點開始向右連續的非負數的個數,ru表示右端點開始向左連續的非負數的個數

  然后每次操作的時候注意一下一種情況就是:

  比如3 2 1,差分之后是3 -1 -1,最多連續的非負數的個數為2,但是答案為3,也就是說所有連續的個數前一個位置其實也可以算作答案


參考代碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
struct node
{int l,r,lc,rc,u,d;int lu,ld,ru,rd;
}tr[110000];int trlen;
void bt(int l,int r)
{int now=++trlen;tr[now].l=l;tr[now].r=r;tr[now].lc=tr[now].rc=-1;tr[now].lu=tr[now].ld=tr[now].ru=tr[now].rd=tr[now].u=tr[now].d=0;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);}
}
void follow(int now)
{int lc=tr[now].lc,rc=tr[now].rc;tr[now].d=max(max(tr[lc].d,tr[rc].d),tr[lc].rd+tr[rc].ld);tr[now].u=max(max(tr[lc].u,tr[rc].u),tr[lc].ru+tr[rc].lu);if(tr[lc].ld==(tr[lc].r-tr[lc].l+1)&&tr[rc].rd==(tr[rc].r-tr[rc].l+1)) tr[now].ld=tr[now].rd=tr[now].r-tr[now].l+1;else if(tr[lc].ld==(tr[lc].r-tr[lc].l+1)&&tr[rc].rd!=(tr[rc].r-tr[rc].l+1)) tr[now].ld=tr[lc].ld+tr[rc].ld,tr[now].rd=tr[rc].rd;else if(tr[lc].ld!=(tr[lc].r-tr[lc].l+1)&&tr[rc].rd==(tr[rc].r-tr[rc].l+1)) tr[now].ld=tr[lc].ld,tr[now].rd=tr[lc].rd+tr[rc].rd;else tr[now].ld=tr[lc].ld,tr[now].rd=tr[rc].rd;if(tr[lc].lu==(tr[lc].r-tr[lc].l+1)&&tr[rc].ru==(tr[rc].r-tr[rc].l+1)) tr[now].lu=tr[now].ru=tr[now].r-tr[now].l+1;else if(tr[lc].lu==(tr[lc].r-tr[lc].l+1)&&tr[rc].ru!=(tr[rc].r-tr[rc].l+1)) tr[now].lu=tr[lc].lu+tr[rc].lu,tr[now].ru=tr[rc].ru;else if(tr[lc].lu!=(tr[lc].r-tr[lc].l+1)&&tr[rc].ru==(tr[rc].r-tr[rc].l+1)) tr[now].lu=tr[lc].lu,tr[now].ru=tr[lc].ru+tr[rc].ru;else tr[now].lu=tr[lc].lu,tr[now].ru=tr[rc].ru;
}
void change(int now,int x,int c)
{if(tr[now].l==tr[now].r){if(c==0) tr[now].u=tr[now].d=tr[now].lu=tr[now].ld=tr[now].ru=tr[now].rd=1;else if(c<0){tr[now].ld=tr[now].rd=tr[now].d=1;tr[now].lu=tr[now].ru=tr[now].u=0;}else{tr[now].ld=tr[now].rd=tr[now].d=0;tr[now].lu=tr[now].ru=tr[now].u=1;}return ;}int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(x<=mid) change(lc,x,c);else change(rc,x,c);follow(now);
}
int tot,p[110000];
void findd(int now,int l,int r)
{if(tr[now].l==l&&tr[now].r==r){p[++tot]=now;return ;}int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;if(r<=mid) findd(lc,l,r);else if(l>mid) findd(rc,l,r);else findd(lc,l,mid),findd(rc,mid+1,r);
}
int a[51000];
int main()
{int n;scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);for(int i=n;i>=1;i--) a[i]=a[i]-a[i-1];trlen=0;bt(1,n);for(int i=1;i<=n;i++) change(1,i,a[i]);int m;scanf("%d",&m);for(int i=1;i<=m;i++){int l,r;scanf("%d%d",&l,&r);tot=0;findd(1,l,r);int ans=0;int dd=0,uu=0;for(int i=1;i<=tot;i++){int d=tr[p[i]].d,u=tr[p[i]].u;if(d!=tr[p[i]].ld) d++;if(u!=tr[p[i]].lu) u++;ans=max(ans,max(d,u));if(tr[p[i]].d==(tr[p[i]].r-tr[p[i]].l+1)) dd+=tr[p[i]].r-tr[p[i]].l+1;else{ans=max(ans,dd+tr[p[i]].ld);dd=tr[p[i]].rd+1;}if(tr[p[i]].u==(tr[p[i]].r-tr[p[i]].l+1)) uu+=tr[p[i]].r-tr[p[i]].l+1;else{ans=max(ans,uu+tr[p[i]].lu);uu=tr[p[i]].ru+1;}ans=max(ans,max(dd,uu));}printf("%d\n",ans);}return 0;
}

?

轉載于:https://www.cnblogs.com/Never-mind/p/8793710.html

總結

以上是生活随笔為你收集整理的BZOJ4491: 我也不知道题目名字是什么的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。