1. 程式人生 > >jzoj 5849.【NOIP提高組模擬2018.8.25】d 排序+權值線段樹

jzoj 5849.【NOIP提高組模擬2018.8.25】d 排序+權值線段樹

Description
這裡寫圖片描述
Input
這裡寫圖片描述
Output
這裡寫圖片描述
Data Constraint
這裡寫圖片描述

分析:
所有矩陣的交集最大面積顯然為min(xi)min(yi)
我們先按長度排序,列舉一個最小值,然後把長度小於當前值的全部刪掉,再從剩下的裡面把寬度最小的一些矩陣刪掉。其實這個東西可以用一個堆維護。考場上打了一個權值線段樹,感覺好顯然啊。

程式碼:

#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#define LL long long const int maxn=1e5+7; const int maxp=1e5; using namespace std; int test,n,m; int t[maxn*4]; LL ans; struct node{ int x,y; }a[maxn]; bool cmp(node x,node y) { return x.x<y.x; } void ins(int p,int l,int r,int x,int k) { if (l==r) { t[p]+=k; return
; } int mid=(l+r)/2; if (x<=mid) ins(p*2,l,mid,x,k); else ins(p*2+1,mid+1,r,x,k); t[p]=t[p*2]+t[p*2+1]; } int getrank(int p,int l,int r,int k) { if (l==r) return l; int mid=(l+r)/2; if (k<=t[p*2]) return getrank(p*2,l,mid,k); else return getrank(p*2
+1,mid+1,r,k-t[p*2]); } int main() { freopen("d.in","r",stdin); freopen("d.out","w",stdout); scanf("%d",&test); while (test--) { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y); sort(a+1,a+n+1,cmp); ans=0; for (int i=n;i>0;i--) { ins(1,1,maxp,a[i].y,1); if (i-1>m) continue; int d=getrank(1,1,maxp,m-(i-1)+1); ans=max(ans,(LL)a[i].x*(LL)d); } for (int i=1;i<=n;i++) ins(1,1,maxp,a[i].y,-1); printf("%lld\n",ans); } }