您的位置:首页 > 其它

JZOJ4898. 【NOIP2016提高A组集训第17场11.16】人生的价值

2016-11-16 22:07 267 查看

Description

NiroBC终于找到了人生的意义,可是她已经老了,在新世界,没有人认识她,她孤独地在病榻上回顾着自己平凡的一生,老泪纵横。NiroBC多么渴望再多活一会儿啊!

突然一个戴着黑色方框眼镜,方脸,穿着高腰裤的长者,乘着圣洁的祥云,飞进了NiroBC的简陋的小屋。

长者说:“你渴望再多活一段时间,再多创造人生的价值吗?”

“愿意!”NiroBC毫不犹豫地回答道。

“生命是宝贵的,不能随便续。你能说出人生的价值究竟是什么吗?只有说对了,我才能给你延续生命。”长者面不改色,嘴角微微扬起鬼魅的笑容。

“那就是不停地吃吃吃吃吃吃吃吃吃吃!”NiroBC思索片刻,用老朽的嗓音吐出了一个又一个“吃”字,足以看出她对食物的渴望。

“对,那我再给你100年生命。”长者点了点头。

长者将NiroBC带回了人间,带回了NiroBC母校YYHS。NiroBC谨记长者的教导,知道吃吃吃才是人生的价值。于是,NiroBC决定用自己在新世界赚得的巨款,为YYHS捐资兴建食堂,确定食堂的位置的问题让NiroBC很头疼。

YYHS的校园可以抽象成一个无限二维平面,校园里分布着N个教室(编号为1..N),第i个教室的坐标为(x[i], y[i]),里面有w[i]个学生。新食堂的饭菜十分美味,然而同学们都比较懒。当且仅当新食堂的位置和第i个教室的位置的曼哈顿距离小于等于L,第i个教室里的学生会去新食堂吃饭。

有博爱之心的NiroBC希望有尽量多的学生去新食堂吃饭,那么这个问题就交给你了!

Solution

我们发现对于一个点,他能扩散的范围实际上是一个菱形。



菱形不好看,于是我们考虑能不能把图翻过来,变成一个正方形。于是我们以(y=x)为新的y轴,(y=-x)为新的x轴,构建一个新的坐标系。所以这就变成一道经典题目。设在新的坐标系中原来为(x,y)的点现在在(x’,y’),那么就有x’(1,-1)+y’(1,1)=(x,y)。解得x’=x−y2,y’=x+y2。缩放一下就有x’=x−y,y’=x+y,矩形边长为2L。

解释一下为什么举例是2*L。设原图中有一个对角线为2 *L的菱形,那么他棱长的距离为2√L。翻转后矩形大小由于缩放*2,边长变为原来的2√倍,于是边长变为2*L。

现在问题变成了在一个平面内求一个被权值覆盖最大的点。我们采用扫描线来解决。我们将点按横坐标为第一关键字,纵坐标为第二关键字排序。对于当前加入的点i,我们维护一个右指针j,使得j点到i点的横坐标之差小于2*L。然后我们以i的纵坐标为下标将i插入线段树。线段树维护的是每个权值向左延伸2 *L个单位的权值和。那么插入操作实质上就是将i的纵坐标到i的纵坐标+2 *L的所有值+i的贡献。更新一下答案。

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100005,maxn1=300005;
struct code{
int a,b,c;
}a[maxn];
int n,i,t,j,k,l,m,x,y,f[4*maxn1],g[4*maxn1],ans;
bool cmp(code x,code y){
return x.a<y.a || x.a==y.a && x.b<y.b;
}
void make(int v){
int y=g[v];f[v*2]+=y;f[v*2+1]+=y;g[v*2]+=y;g[v*2+1]+=y;g[v]=0;
}
void insert(int l,int r,int v,int x,int y,int z){
int mid=(l+r)/2;
if (g[v] && l!=r) make(v);
if (l>=x && r<=y){
f[v]+=z;
g[v]+=z;
return;
}
if (l<=y && mid>=x) insert(l,mid,v*2,x,y,z);
if (mid<y && r>=x) insert(mid+1,r,v*2+1,x,y,z);
f[v]=max(f[v*2],f[v*2+1]);
}
int main(){
freopen("value.in","r",stdin);freopen("value.out","w",stdout);
scanf("%d%d",&n,&m);m=m*2;
for (i=1;i<=n;i++)
scanf("%d%d%d",&x,&y,&a[i].c),a[i].a=x-y+maxn,a[i].b=x+y+maxn;
sort(a+1,a+n+1,cmp);j=1;
for (i=1;i<=n;i++){
while (a[i].a-a[j].a>m) insert(1,maxn1,1,a[j].b,min(maxn1,a[j].b+m),-a[j].c),j++;
insert(1,maxn1,1,a[i].b,min(maxn1,a[i].b+m),a[i].c);t=0;
ans=max(f[1],ans);
}
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: