BZOJ 3476: [Usaco2014 Mar]The Lazy Cow

35 篇文章 0 订阅
20 篇文章 0 订阅

呜呜呜 这题弄了我好久

有一点很重要的是 你要看出一个点按照曼哈顿距离刚好就是围出来一个正方形 与坐标轴成45°

我们要让他与坐标轴平行 方便我们搞

然后就要把它“旋转一下” 然而我并不会QAQ 看了别人的之后大概知道 坐标变成 x+y,x-y 纵坐标避免负值都加上10^6

至于为什么 可以自行百度旋转坐标系

有个大神告诉我 你会发现正方形里一条边上的点 要弄成与坐标轴平行 所以x或者y是相等 接着同一条线的增幅是一样的 x都递增或减  y都递增或减  这样一加或者一减 就能达到x或y相等啦~(%%%%%hyc+部分自己脑补QAQ)

不懂的自己画一下就好啦,同时就顺便得到k变成2k 继续求曼哈顿距离~\(≧▽≦)/~

然后按其中一个排序一下 线段树搞一下就好了


本来愚蠢的我都不想写出来了

不过代码排18那么6 还是贴出来顺便写个题解蹭访问量(真的挺短挺好看 而且挺快~)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N=100005,M=1e6+1,inf=1e9;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
struct node{int x,y,c;}a[N];
int Cmp(node x1,node x2){return x1.y<x2.y;}
int lazy[M<<3],mx[M<<3];
void pushdown(int x)
{
    int lc=x<<1,rc=lc|1;
    if(lazy[x]!=0)
    {
        int lz=lazy[x]; lazy[x]=0;
        lazy[lc]+=lz,lazy[rc]+=lz;
        mx[lc]+=lz,mx[rc]+=lz;
    }
}
void change(int x,int l,int r,int ql,int qr,int u)
{
    if(l!=r)pushdown(x);
    if(l==ql && r==qr){
        lazy[x]+=u,mx[x]+=u;
        return;
    }
    int lc=x<<1,rc=lc|1,mid=(l+r)>>1;
    if(ql>mid)change(rc,mid+1,r,ql,qr,u);
    else if(qr<=mid)change(lc,l,mid,ql,qr,u);
    else
    {
        change(lc,l,mid,ql,mid,u);
        change(rc,mid+1,r,mid+1,qr,u);
    }
    mx[x]=max(mx[lc],mx[rc]);
}
int main()
{
    int n=read(),k=read(),i,x,y,Max,Min;
    k<<=1; Max=1,Min=inf;
    for(i=1;i<=n;i++)
    {
        a[i].c=read(),x=read(),y=read();
        a[i].x=x+y,a[i].y=x-y+M;
        Max=max(a[i].x,Max),Min=min(a[i].x,Min);
    }
    sort(a+1,a+1+n,Cmp);
    int l=0,r=0,ans=0;
    while(l<=n)
    {
        int ly=a[l].y;
        while(a[l].y==ly && l<=n)
        {
            if(l!=0)change(1,Min,Max,a[l].x,min(a[l].x+k,Max),-a[l].c);
            l++;
        }
        while(a[r+1].y-a[l].y<=k && r<n)
        {
            r++;
            change(1,Min,Max,a[r].x,min(a[r].x+k,Max),a[r].c);
        }
        ans=max(ans,mx[1]);
    }
    printf("%d\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值