【笛卡尔树】【树状数组】Beautiful Pair(P4755)
生活随笔
收集整理的這篇文章主要介紹了
【笛卡尔树】【树状数组】Beautiful Pair(P4755)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
P4755
題目大意
給你n個(gè)數(shù),問你有多少對(duì)二元組 (i,j)(i,j)(i,j) 滿足 i≤ji\leq ji≤j 且 ai×aj≤maxi=ijaia_i\times a_j\leq max_{i=i}^ja_iai?×aj?≤maxi=ij?ai?
解題思路
考慮對(duì)原數(shù)組構(gòu)建笛卡爾樹,樹中左右子樹之間的二元組所取得的max就是當(dāng)前節(jié)點(diǎn)
考慮啟發(fā)式合并,把大的子樹存到樹狀數(shù)組,然后小的子樹直接暴力計(jì)算答案
時(shí)間復(fù)雜度 O(nlog2n)O(n\ log^2\ n)O(n?log2?n)
code
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 100100 using namespace std; ll n,m,ans,a[N],c[N],g[N],b[N],lg[N],f[N][20]; ll get(ll l,ll r) {ll g=lg[r-l+1];if(a[f[l][g]]>a[f[r-(1<<g)+1][g]])return f[l][g];else return f[r-(1<<g)+1][g]; } void add(ll x) {x=upper_bound(b+1,b+1+m,x)-b-1;for(;x<=m;x+=x&-x)c[x]++;return; } ll ask(ll x) {x=upper_bound(b+1,b+1+m,x)-b-1;ll sum=0;for(;x;x-=x&-x)sum+=c[x];return sum; } void dfs(ll l,ll r) {if(l>r)return;ll x=get(l,r);if(x-l<r-x){g[x]=ask(1);for(ll i=l;i<x;++i)g[i]=ask(a[x]/a[i]);dfs(x+1,r);add(a[x]);for(ll i=l;i<x;++i)ans+=ask(a[x]/a[i])-g[i];ans+=ask(1)-g[x];dfs(l,x-1);}else{g[x]=ask(1);for(ll i=x+1;i<=r;++i)g[i]=ask(a[x]/a[i]);dfs(l,x-1);add(a[x]);for(ll i=x+1;i<=r;++i)ans+=ask(a[x]/a[i])-g[i];ans+=ask(1)-g[x];dfs(x+1,r);}return; } int main() {scanf("%lld",&n);for(ll i=1;i<=n;++i){scanf("%lld",&a[i]);b[i]=a[i];f[i][0]=i;}sort(b+1,b+1+n);m=unique(b+1,b+1+n)-b-1;for(ll i=2;i<=n;++i)lg[i]=lg[i>>1]+1;for(ll j=1;j<=16;++j)for(ll i=1;i<=n-(1<<j-1);++i)if(a[f[i][j-1]]>a[f[i+(1<<j-1)][j-1]])f[i][j]=f[i][j-1];else f[i][j]=f[i+(1<<j-1)][j-1];dfs(1,n);printf("%lld",ans);return 0; }總結(jié)
以上是生活随笔為你收集整理的【笛卡尔树】【树状数组】Beautiful Pair(P4755)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑无法开机怎么解决笔记本电脑无法开机怎
- 下一篇: 【贪心】数据备份(P6320)