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

题目描述

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希望有尽量多的学生去新食堂吃饭,那么这个问题就交给你了!

数据范围

这里写图片描述

=w=

旋转坐标系后,放缩。于是就把曼哈顿距离转化为切比雪夫距离,原问题就转化成有很多个正方形,取一个点使得包含这个点的所有正方形的权值和最大。
显然我们可以使用差分和数据结构来做。

代码

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define ll long long
using namespace std;
const char* fin="value.in";
const char* fout="value.out";
const int inf=0x7fffffff;
const int maxn=100007,maxa=200017,maxt=maxa*4;
int n,m,i,j,k,l,r,ans,tmp;
int tot=0;
int c[maxt],mk[maxt];
struct node{
    int x,y,z;
}a[maxn];
struct event{
    int id,k,x;
}b[maxn*2];
bool cmp(event a,event b){
    return a.x<b.x;
}
void markdown(int l,int r,int t){
    c[t]+=mk[t];
    if (l!=r){
        mk[t*2]+=mk[t];
        mk[t*2+1]+=mk[t];
    }
    mk[t]=0;
}
void change(int l,int r,int t,int v1,int v2,int v){
    int mid=(l+r)/2;
    markdown(l,r,t);
    if (l>v2 || r<v1) return ;
    if (l>=v1 && r<=v2){
        mk[t]+=v;
        markdown(l,r,t);
        return;
    }
    change(l,mid,t*2,v1,v2,v);
    change(mid+1,r,t*2+1,v1,v2,v);
    c[t]=max(c[t*2],c[t*2+1]);
}
int getmax(int l,int r,int t,int v1,int v2){
    int mid=(l+r)/2;
    markdown(l,r,t);
    if (l>v2 || r<v1) return 0;
    if (l>=v1 && r<=v2) return c[t];
    return max(getmax(l,mid,t*2,v1,v2),getmax(mid+1,r,t*2+1,v1,v2));
}
int main(){
    freopen(fin,"r",stdin);
    freopen(fout,"w",stdout);
    scanf("%d%d",&n,&m);
    int maxy=maxa-1;
    for (i=1;i<=n;i++){
        scanf("%d%d%d",&j,&k,&a[i].z);
        a[i].x=maxn+j-k;
        a[i].y=j+k;
        b[++tot].x=max(1,a[i].x-m);
        b[tot].k=1;
        b[tot].id=i;
        b[++tot].x=min(maxy,a[i].x+m+1);
        b[tot].k=-1;
        b[tot].id=i;
    }
    sort(b+1,b+tot+1,cmp);
    l=1;
    for (i=1;i<maxa;i++){
        while (l<=tot & b[l].x==i){
            j=b[l].id;
            change(1,maxy,1,max(1,a[j].y-m),min(maxy,a[j].y+m),a[j].z*b[l].k);
            l++;
        }
        ans=max(ans,getmax(1,maxy,1,1,maxa));
    }
    printf("%d",ans);
    return 0;
}

=o=

比赛的时候也想差分,但是囿于曼哈顿距离的局限性,无法完成。
后来觉得如果是切比雪夫距离的话,会好做很多。
但是并不知道切比雪夫距离和曼哈顿距离可以相互转化
于是就懵逼了。

原文地址:https://www.cnblogs.com/hiweibolu/p/6714826.html