[二分][树状数组] Jzoj P5849 d

Description

 

Input

Output

 

Sample Input

见下发文件

Sample Output

见下发文件
 
 

Data Constraint

题解

  • 这题,题目说可以任意移动矩阵,那么就可以把所有矩阵的左上角移到(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 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9648826.html