1. 程式人生 > >luogu P4755 Beautiful Pair - 啟發式合併 - 主席樹

luogu P4755 Beautiful Pair - 啟發式合併 - 主席樹

題目大意:
給一個非負整數數列,問有多少子區間,端點權值乘積小於等於區間最大值。
(其實是啟發式分裂?
這個題做法一模一樣,沒了。

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 998244353
#define N 100010
#define db long double
#define pb push_back #define mp make_pair #define fir first #define sec second #define debug(x) cerr<<#x<<"="<<x #define sp <<" " #define ln <<endl using namespace std; typedef pair<int,int> pii; typedef set<int>::iterator sit; inline int inn() { int x,
ch;while((ch=gc)<'0'||ch>'9'); x=ch^'0';while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');return x; } pii b[N];vector<int> v;int L[N],R[N],st[N],m,a[N],zo[N];set<int> s; inline bool cmp(pii a,pii b) { return a.fir!=b.fir?a.fir>b.fir:a.sec<
b.sec; } inline int getid(int x) { return lower_bound(v.begin(),v.end(),x)-v.begin()+1; } struct segment{ int s;segment *ch[2]; }*T[N]; int build(segment* &rt,int l,int r) { rt=new segment,rt->s=0;int mid=(l+r)>>1;if(l==r) return 0; return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r); } int update(segment* &x,segment* &y,int p,int l,int r) { x=new segment,x->ch[0]=y->ch[0],x->ch[1]=y->ch[1]; x->s=y->s+1;if(l==r) return 0;int mid=(l+r)>>1; if(p<=mid) update(x->ch[0],y->ch[0],p,l,mid); else update(x->ch[1],y->ch[1],p,mid+1,r);return 0; } int query(segment* &x,segment* &y,int s,int t,int l,int r) { if(s<=l&&r<=t) return x->s-y->s;int mid=(l+r)>>1,ans=0; if(s<=mid) ans+=query(x->ch[0],y->ch[0],s,t,l,mid); if(mid<t) ans+=query(x->ch[1],y->ch[1],s,t,mid+1,r); return ans; } inline int query(int L,int R,int s,int t) { if(L>R||s>t) return 0; if(R-L<=40) { int ans=0;rep(i,L,R) ans+=(a[i]>=s&&a[i]<=t);return ans; } int x=getid(s),y=getid(t); if(v[y-1]>t) y--;if(x>y) return 0; return query(T[R],T[L-1],x,y,1,m); } int main() { //freopen("data.in","r",stdin),freopen("std.out","w",stdout); int n=inn();rep(i,1,n) a[i]=inn(),v.pb(a[i]); sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); m=(int)v.size(),build(T[0],1,m); rep(i,1,n) update(T[i],T[i-1],getid(a[i]),1,m); rep(i,1,n) L[i]=1,R[i]=n;lint ans=0; for(int i=1,t=0;i<=n;st[++t]=i++) while(t&&a[st[t]]<a[i]) R[st[t--]]=i-1; for(int i=n,t=0;i>=1;st[++t]=i--) while(t&&a[st[t]]<=a[i]) L[st[t--]]=i+1; rep(i,1,n) zo[i]=zo[i-1]+(a[i]<=1); s.insert(0),s.insert(n+1); rep(i,1,n) b[i]=mp(a[i],i); sort(b+1,b+n+1,cmp); for(int i=1;i<=n;i++) { int x=b[i].sec,L,R; sit it=s.lower_bound(x); R=(*it)-1,it--,L=(*it)+1; if(a[x]) ans+=zo[R]-zo[L-1]; else ans+=R-L+1; int Llen=x-L,Rlen=R-x; if(Llen<=Rlen) rep(j,L,x-1) ans+=(a[j]?query(x+1,R,0,a[x]/a[j]):Rlen); else rep(j,x+1,R) ans+=(a[j]?query(L,x-1,0,a[x]/a[j]):Llen); s.insert(x); } return !printf("%lld\n",ans); }