2369. 区间

2369. 区间

决策单调性

首先我们处理区间,如果这个区间被其它区间包含,那么我们暂时不考虑它

处理完之后,所有区间呈现出\(l,r\)递增,选出的区间集合一定是一段连续的区间

然后我们决策单调性分治求解,单调性: \(j\)\(i\)的递增而递增

对于那些被包含的区间,上面提到的情况一定不会产生贡献(取那段包含它的区间一定更优)

还有一种情况,就是被包含的区间和包含它的区间之间产生贡献,就是选一段最长的包含它的区间算贡献即可

const int N=1e6+10;
  
int n,m;
  
struct Node{
    int l,r;
} A[N];
  
struct CMP{
    bool operator () (const Node a,const Node b){
        if(a.l!=b.l) return a.l<b.l;
        return a.r>b.r;
    }
};
  
inline void chk(ll &x,ll y){ ((x<y)&&(x=y)); }
inline void chk(int &x,int y){ ((x<y)&&(x=y)); }
  
ll ans;
void Solve(int l,int r,int L,int R){
    if(l>r) return;
    int mid=(l+r)>>1;
    ll ma=-1e18,id=0;
    rep(i,max(L,mid+1),R) {
        ll t=1ll*(A[mid].r-A[i].l)*(A[i].r-A[mid].l);
        ((t>ma)&&(ma=t,id=i));
    }
    chk(ans,ma);
    Solve(l,mid-1,L,id);
    Solve(mid+1,r,id,R);
}
int s[N];
void Add(int p,int x) {
    p++;
    while(p) chk(s[p],x),p-=p&-p;
}
int Que(int p) {
    p++;
    int res=0;
    while(p<N) chk(res,s[p]),p+=p&-p;
    return res;
}
  
int main(){
    n=rd();
    rep(i,1,n) A[i].l=rd(),A[i].r=rd();
    sort(A+1,A+n+1,CMP());
    int ma=0;
    rep(i,1,n) {
        if(A[i].r<=A[i].l) continue;
        if(ma<A[i].r) {
            A[++m]=A[i];
            ma=A[i].r;
            Add(A[i].r,A[i].r-A[i].l);
        } else chk(ans,1ll*Que(A[i].r)*(A[i].r-A[i].l));//被包含时,选一段最长的包含它的区间,即lj<=li
    }
    n=m;
    Solve(1,n,1,n);
    printf("%lld\n",ans);
}
原文地址:https://www.cnblogs.com/chasedeath/p/11743398.html