[二分][树状数组] Jzoj P5849 d
题解
- 这题,题目说可以任意移动矩阵,那么就可以把所有矩阵的左上角移到(0,0)
- 这样的话,其实就可以不用管了这个东西了
- 然后,我们可以先将横坐标排序,然后把y坐标加进树状数组,权值为1
- 枚举x坐标,然后二分y坐标mid,然后将y坐标小于mid的全部删掉+重复的有没有大于m
- 最后更新ans
代码
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 int t,n,m,sz[100010]; 5 struct edge {int x,y;}e[100010]; 6 bool cmp(edge a,edge b) { return (a.x<b.x)||(a.x==b.x&&a.y<b.y); } 7 void insert(int x,int d) { for (;x<=100000;x+=x&-x) sz[x]+=d; } 8 int query(int x) 9 { 10 int r=0; 11 for (;x;x-=x&-x) r+=sz[x]; 12 return r; 13 } 14 bool check(int x,int y) { return (query(y-1)+x<=m)?1:0; } 15 int main() 16 { 17 freopen("d.in","r",stdin); 18 freopen("d.out","w",stdout); 19 scanf("%d",&t); 20 while (t--) 21 { 22 scanf("%d%d",&n,&m); 23 int mxx=0,p=0,mxy=0; long long ans=0; 24 for (int i=1;i<=n;i++) scanf("%d%d",&e[i].x,&e[i].y),mxx=max(mxx,e[i].x),mxy=max(mxy,e[i].y); 25 sort(e+1,e+n+1,cmp); 26 for (int i=1;i<=n;i++) insert(e[i].y,1); 27 for (int i=1;i<=n;i++) 28 { 29 int k=i,l=1,r=mxy,mx=0; 30 while (e[k].x==e[k+1].x&&k<n) k++; 31 while (l<=r) 32 { 33 int mid=(l+r)>>1; 34 if (check(p,mid)) mx=mid,l=mid+1; else r=mid-1; 35 } 36 for (int j=i;j<=k;j++) insert(e[j].y,-1),p++; 37 ans=max(ans,1ll*e[i].x*mx); 38 i=k; 39 } 40 printf("%lld\n",ans); 41 } 42 }