[树状数组] Jzoj P4737 金色丝线将瞬间一分为二

Description

 

Input

Output

 

Sample Input

5 10
1 1
2 2
3 3
4 4
5 5

Sample Output

4
 

Data Constraint

 

Hint


 

 

题解

  • 先定义两个数组rank1和rank2表示以x或y坐标从小到大排序后第i个点的排名
  • 那么弄出这两个数组之后,每次加上做到的点i到所有前面的点的距离
  • 可以用两个树状数组来做,一个记录的是x坐标一个是y坐标
  • 那么,就是先将1~rank1[i]排名的遗体的个数和x坐标和求出来,总距离加上num*x[i]-sumx
  • 然后还有求出rank1[i]+1~n排名的遗体的个数和x坐标和求出来,总距离就是sumx-num*x[i]
  • y的做法同上

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 using namespace std;
 5 long long sz1[600010],sz2[600010],x[600010],y[600010],s,num,sumx,sumy,d;
 6 int n,cnt1[600010],cnt2[600010],rank1[600010],rank2[600010],d1[600010],d2[600010];
 7 bool cmpx(int a,int b) { return x[a]<x[b]; }
 8 bool cmpy(int a,int b) { return y[a]<y[b]; }
 9 void insert1(int x,int y) 
10 { 
11     for (;x<=n;x+=x&-x) sz1[x]+=y,cnt1[x]++; 
12 }
13 void insert2(int x,int y) 
14 { 
15     for (;x<=n;x+=x&-x) sz2[x]+=y,cnt2[x]++; 
16 }
17 long long getsum1(int x,long long &y) 
18 { 
19     long long s=0;
20     for (;x;x-=x&-x) s+=sz1[x],y+=cnt1[x];
21     return s;
22 }
23 long long getsum2(int x,long long &y) 
24 { 
25     long long s=0;
26     for (;x;x-=x&-x) s+=sz2[x],y+=cnt2[x];
27     return s;
28 }
29 long long query1(int l,int r,long long &num)
30 {
31     long long tot=0,s=getsum1(r,num)-getsum1(l-1,tot);
32     num-=tot;
33     return s;
34 }
35 long long query2(int l,int r,long long &num)
36 {
37     long long tot=0,s=getsum2(r,num)-getsum2(l-1,tot);
38     num-=tot;
39     return s;
40 }
41 int main()
42 {
43     scanf("%d%lld",&n,&d);
44     for (int i=1;i<=n;i++)
45     {
46         scanf("%lld%lld",&x[i],&y[i]);
47         d1[i]=d2[i]=i;
48     }
49     sort(d1+1,d1+n+1,cmpx);
50     sort(d2+1,d2+n+1,cmpy);
51     for (int i=1;i<=n;i++) rank1[d1[i]]=i,rank2[d2[i]]=i;
52     for (int i=1;i<=n;i++)
53     {
54         num=0,sumx=query1(1,rank1[i],num),s+=num*x[i]-sumx;
55         num=0,sumx=query1(rank1[i],n,num),s+=sumx-num*x[i];
56         num=0,sumy=query2(1,rank2[i],num),s+=num*y[i]-sumy;
57         num=0,sumy=query2(rank2[i],n,num),s+=sumy-num*y[i];
58         if (s>d)
59         {
60             printf("%d",i);
61             return 0;
62         }
63         insert1(rank1[i],x[i]),insert2(rank2[i],y[i]);
64     }
65     printf("-1");
66     return 0;
67 }

 

posted @ 2018-08-21 16:12  BEYang_Z  阅读(189)  评论(0编辑  收藏  举报