首页 > 代码库 > 【BZOJ 3476】 线段树===

【BZOJ 3476】 线段树===

59  懒惰的奶牛
贝西所在的牧场,散落着 N 堆牧草,其中第 i 堆牧草在 ( Xi,Yi ) 的位置,数量有 Ai 个单位。
贝西从家移动到某一堆牧草的时候,只能沿坐标轴朝正北、正东、正西、正南这四个方向移
动,所以计算贝西和牧草间的距离时,应采用“曼哈顿距离”—— (x,y ) 和 (x ,y ) 之间的距离为
|x ? x | + |y ? y |。例如贝西的家在 (0.5, 0.3),有一堆牧草在 (3, 2),那么它们之间的距离就是 4.2。
贝西懒得走动,她想请你为它寻找一个最好的位置作为家,这个家附近距离不超过 K 的牧草数
量之和是最大的。注意家的坐标可以不是整数,也可以和某堆牧草的坐标完全重合。
输入格式
? 第一行:两个整数 N K, 1 N 100000, 1 K 2000000
? 第二行到第 N + 1 行:第 i + 1 行有三个整数: Ai, Xi Yi, 1 Ai 10000, 0 Xi,Yi
1000000
输出格式
? 单个整数:表示距离和最佳位置不超过 K 的牧草数量之和
样例输入
4 3
7 8 6
3 0 0
4 6 0
1 4 2
样例输出
8
解释
选择 (3, 0) 为家,位置在 (0, 0), (6, 0) 和
(4, 2) 的牧草距离家都不超过 K
来源
The Lazy Cow, 2014 Mar

 

【分析】

  曼哈顿距离的话,那个范围,应该是一个边长和坐标轴呈45度角的正方形。

  这样就有点难搞,难统计。

  我们需要把图形“旋转一下”

  旋转的目标是让正方形的边长平行于坐标轴。、

  那么,观察一下可以得到,可以把nx=x-y ny=x+y 这样就旋转过来了(其实改变了正方形的大小的,但没有关系,只要能判断出曼哈顿距离是不是<=k就好)

 然后就很简单了,用线段树维护y纵坐标,然后x横坐标线性扫描。

 

代码如下:

技术分享
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<cmath>
  8 using namespace std;
  9 #define Maxn 2000010
 10  
 11 struct hp
 12 {
 13     int a,ax,ay;
 14 }tt[Maxn];
 15  
 16 struct node
 17 {
 18     int l,r,lc,rc,ans;
 19     int lazy;
 20 }t[2*Maxn];int len;
 21  
 22 int mymin(int x,int y) {return x<y?x:y;}
 23 int mymax(int x,int y) {return x>y?x:y;}
 24  
 25 bool cmp(hp x,hp y) {return x.ax<y.ax;}
 26 int n,k;
 27  
 28 int build(int l,int r)
 29 {
 30     int x=++len;
 31     t[x].l=l;t[x].r=r;
 32     t[x].ans=0;t[x].lazy=0;
 33     if(l!=r)
 34     {
 35         int mid=(l+r)>>1;
 36         t[x].lc=build(l,mid);
 37         t[x].rc=build(mid+1,r);
 38     }
 39     else t[x].lc=t[x].rc=0;
 40     return x;
 41 }
 42  
 43 void init()
 44 {
 45     scanf("%d%d",&n,&k);
 46     int mx=0;
 47     for(int i=1;i<=n;i++)
 48     {
 49         scanf("%d%d%d",&tt[i].a,&tt[i].ax,&tt[i].ay);
 50         int xx=tt[i].ax;
 51         tt[i].ax=tt[i].ax-tt[i].ay;tt[i].ay=xx+tt[i].ay+1;
 52         mx=mymax(mx,tt[i].ay);
 53     }
 54     sort(tt+1,tt+1+n,cmp);
 55     k=k*2;
 56     build(1,mx);
 57 }
 58  
 59 void upd(int x)
 60 {
 61     if(t[x].lazy==0) return;
 62     t[x].ans+=t[x].lazy;
 63     int lc=t[x].lc,rc=t[x].rc;
 64     if(t[x].l!=t[x].r)
 65     {
 66         t[lc].lazy+=t[x].lazy;
 67         t[rc].lazy+=t[x].lazy;
 68     }
 69     t[x].lazy=0;
 70 }
 71  
 72 void change(int x,int l,int r,int y)
 73 {
 74     if(t[x].l==l&&t[x].r==r)
 75     {
 76         t[x].lazy+=y;
 77         return;
 78     }
 79     upd(x);
 80     int mid=(t[x].l+t[x].r)>>1;
 81     if(r<=mid) change(t[x].lc,l,r,y);
 82     else if(l>mid) change(t[x].rc,l,r,y);
 83     else
 84     {
 85         change(t[x].lc,l,mid,y);
 86         change(t[x].rc,mid+1,r,y);
 87     }
 88     upd(t[x].lc);upd(t[x].rc);
 89     t[x].ans=mymax(t[t[x].lc].ans,t[t[x].rc].ans);
 90 }
 91  
 92 void ffind()
 93 {
 94     int j=0,ans=0;
 95     for(int i=1;i<=n;i++)
 96     {
 97         while(j<n&&tt[j+1].ax-tt[i].ax<=k)
 98         {
 99             int nx=mymax(1,tt[j+1].ay-k);
100             change(1,nx,tt[j+1].ay,tt[j+1].a);
101             j++;
102         }
103         upd(1);
104         ans=mymax(ans,t[1].ans);
105         change(1,mymax(1,tt[i].ay-k),tt[i].ay,-tt[i].a);
106     }
107     printf("%d\n",ans);
108 }
109  
110 int main()
111 {
112     init();
113     ffind();
114     return 0;
115 }
bzoj 3476

 

2016-10-31 11:25:57

【BZOJ 3476】 线段树===