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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

牛客 - 骚区间(线段树+思维)

發布時間:2024/4/11 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客 - 骚区间(线段树+思维) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個 1 ~ n 的排列 a?,現在規定騷區間當且僅當 a[ l ] 是 [ l , r ] 這段區間內的次小值,同時 a[ r ] 是 [ l , r ] 這段區間內的次大值,現在問有多少個子區間(連續)是sao的

題目分析:一段對兩個端點都有約束的區間,在確定下來一個端點后,根據條件不難確定出另一個端點的可行范圍

但為了確定有多少左右區間可以配對,我們可以利用線段樹和掃描線的思想進行維護

枚舉端點 i 作為左端點時,找到右端點的可行區間 [ l , r ] ,將點 l 的標記打上 { i , 1 } ,點 r + 1 的標記打上 { i , - 1 }?

然后更新點 i 的標記到線段樹上,如果標記的第二個值為 1 ,說明將第一個添加到線段樹上,- 1 代表刪除

最后令點 i 作為右端點,找到左端點的可行區間 [ L , R ] ,在線段樹上統計區間 [ L , R ] 內有多少個數,就說明有多少個數可以在點 i 作為右端點時,作為左端點與其匹配

只是單純的一種可以解決對區間兩個端點存在約束的配對問題的方法,實現起來的話線段樹也可以用樹狀數組代替,時間復雜度 nlogn

代碼:
?

#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;vector<int>pos[N];int c[N],cnt[N],a[N],n;int lowbit(int x) {return x&(-x); }void update(int pos,int val) {while(pos<N){c[pos]+=val;pos+=lowbit(pos);} }int query(int pos) {int ans=0;while(pos){ans+=c[pos];pos-=lowbit(pos);}return ans; }struct Node {int l,r;int mmin,mmax; }tree[N<<2];void pushup(int k) {tree[k].mmin=min(tree[k<<1].mmin,tree[k<<1|1].mmin);tree[k].mmax=max(tree[k<<1].mmax,tree[k<<1|1].mmax); }void build(int k,int l,int r) {tree[k].l=l;tree[k].r=r;if(l==r){tree[k].mmax=tree[k].mmin=a[l];return;}int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k); }int query_min(int k,int l,int r,int val)//返回區間[l,r]內小于val的最小位置 {if(l>r)return n+1;if(tree[k].l>r||tree[k].r<l)return n+1;if(tree[k].mmin>=val)return n+1;if(tree[k].l==tree[k].r)return tree[k].l;int temp=query_min(k<<1,l,r,val);if(temp!=n+1)return temp;return query_min(k<<1|1,l,r,val); }int query_max(int k,int l,int r,int val)//返回區間[l,r]內大于val的最大位置 {if(l>r)return 0;if(tree[k].l>r||tree[k].r<l)return 0;if(tree[k].mmax<=val)return 0;if(tree[k].l==tree[k].r)return tree[k].l;int temp=query_max(k<<1|1,l,r,val);if(temp!=0)return temp;return query_max(k<<1,l,r,val); }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",a+i);build(1,1,n);LL ans=0;for(int i=1;i<=n;i++){int l=query_min(1,i,n,a[i]),r=query_min(1,l+1,n,a[i]);pos[l].push_back(i);pos[r].push_back(-i);for(auto v:pos[i]){if(v>0){if(cnt[v]==0)update(v,1);cnt[v]++;}else{cnt[-v]--;if(cnt[-v]==0)update(-v,-1);}}r=query_max(1,1,i,a[i]),l=query_max(1,1,r-1,a[i]);ans+=query(r)-query(l);}printf("%lld\n",ans);return 0; }

?

總結

以上是生活随笔為你收集整理的牛客 - 骚区间(线段树+思维)的全部內容,希望文章能夠幫你解決所遇到的問題。

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