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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

洛谷 - P4755 Beautiful Pair(笛卡尔树+主席树)

發(fā)布時間:2024/4/11 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 洛谷 - P4755 Beautiful Pair(笛卡尔树+主席树) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個長度為 n 的數(shù)列 a,現(xiàn)在一個數(shù)對 ( i , j ) 如果滿足 a[ i ] * a[ j?] <=max( a[ i ] ~ a[ j ]?),則稱其為美麗的,求出美麗對的數(shù)量

題目分析:直接統(tǒng)計是比較困難的,但正難則反,我們可以枚舉每個數(shù)作為最大值時,在其管轄的區(qū)間內(nèi)進(jìn)行統(tǒng)計,對于某個最大值 i 來說,肯定存在著 l[ i ] 和 r[ i ] ,使得 l[ i ] - 1 是 i 左側(cè)首個大于 a[ i ] 的位置,r[ i ] + 1 是 i 右側(cè)首個大于 a[ i ] 的位置,這樣在區(qū)間 [ l[ i ] , r[ i ] ] 中,跨過位置 i 時的最大值一定是 a[ i ] ,于是區(qū)間就被分成了兩段:[ l[ i ] , i ] , [ i , r[ i ] ],因為乘積運算滿足交換律,所以遍歷長度較小的一段,在另一段中查找符合條件的元素的個數(shù)即可,假設(shè)當(dāng)前枚舉的數(shù)字為 a[ j ] ,最大值為 a[ i ] ,所以需要在區(qū)間內(nèi)查找 [ 1 , a[ i ] / a[ j ] ] 的元素個數(shù),這顯然是線段樹的功能,不過如果放在區(qū)間上詢問的話,就需要可持久化一下來使用,也就是主席樹了,對于上述找 l[ i ] 和 r[ i ] 的過程,可以用笛卡爾樹來完成,然后 dfs 一遍統(tǒng)計答案就好了

代碼:
?

#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> #include<bitset> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;int a[N];LL ans; /*主席樹*/ struct Node1 {int l,r;int sum; }tree[N*35];int cnt,root[N];void update(int num,int &k,int l,int r) {tree[cnt++]=tree[k];k=cnt-1;tree[k].sum++;if(l==r)return;int mid=l+r>>1;if(num<=mid)update(num,tree[k].l,l,mid);elseupdate(num,tree[k].r,mid+1,r); }int query(int i,int j,int L,int R,int l,int r)//i:左端點根節(jié)點編號,j:右端點根節(jié)點編號,l,r:目標(biāo)區(qū)間,L,R:當(dāng)前區(qū)間 {if(l>r)return 0;if(R<l||L>r)return 0;if(L>=l&&R<=r)return tree[j].sum-tree[i].sum;int mid=L+R>>1;return query(tree[i].l,tree[j].l,L,mid,l,r)+query(tree[i].r,tree[j].r,mid+1,R,l,r); } /*主席樹*/ /*笛卡爾樹*/ struct Node2 {int l,r,val; }t[N];stack<int>s;void insert(int x) {while(s.size()&&t[s.top()].val<t[x].val)s.pop();t[x].l=t[s.top()].r;//x->lsont[s.top()].r=x;//fa->x(rson)s.push(x); } /*笛卡爾樹*/ void dfs(int k,int l,int r) {if(k==0)//特判一下根 {if(t[k].l)dfs(t[k].l,l,r);if(t[k].r)dfs(t[k].r,l,r);return;}if(k-l<=r-k)//遍歷左區(qū)間 for(int i=l;i<=k;i++)ans+=query(root[k-1],root[r],1,inf,1,t[k].val/t[i].val);else//遍歷右區(qū)間 for(int i=k;i<=r;i++)ans+=query(root[l-1],root[k],1,inf,1,t[k].val/t[i].val);if(t[k].l)dfs(t[k].l,l,k-1);if(t[k].r)dfs(t[k].r,k+1,r); }void init() {t[0].val=inf;t[0].l=t[0].r=0;s.push(0);root[0]=0;tree[0].l=tree[0].r=tree[0].sum=0;cnt=1; }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);init();int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&t[i].val);insert(i);root[i]=root[i-1];update(t[i].val,root[i],1,inf);}dfs(0,1,n);printf("%lld\n",ans);return 0; }

?

總結(jié)

以上是生活随笔為你收集整理的洛谷 - P4755 Beautiful Pair(笛卡尔树+主席树)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。