UVA - 12074 The Ultimate Bamboo Eater 二维线段树

Time Limit:3000MS Memory Limit:Unknown 64bit IO Format:%lld & %llu

Status

Description

Download as PDF

Jingjing the panda lives in a forest containing n pieces of bamboo land. Each bamboo land is very small and can be regarded as a single point. Bamboo land i contains Li bamboos and is associated with a ``deliciousness'' Wi .

\epsfbox{p3294.eps}

Jingjing eats all bamboos in a selected bamboo land every day. He has a bad habit: the deliciousness of the bamboo land he selects must be strictly larger than that of the day before.

Moving from one land to another is very tiring. The longer Jingjing walks before arriving a bamboo land i , the more bamboo he is expecting. If the distance he walked from the last bamboo land is strictly larger than the number of bamboos he finds in the current land (i.e Li ), he will die of sadness.

Distance of two points (x0, y0) and (x1, y1) equals to | x0 - x1| + | y0 - y1| , since Jingjing only moves north, south, east and west.

When you send Jingjing in one bamboo land someday, how many days can Jingjing survive (Jingjing is clever enough to find out the optimal way of living)?

We need this information so that we can bring him out before he dies.

Input 

The first line contains a single integer t ( 1$ \le$t$ \le$10 ), the number of test cases. Each test case contains several lines.

The first line contains a single integer n ( 1$ \le$n$ \le$100, 000 ), the number of bamboo lands. The next n lines each contains 4 integers Xi , Yi , Wi , Li , indicating the coordinate of i -th bamboo land, its deliciousness and number of bamboos.

You may assume that 0$ \le$Xi, Yi, Wi, Li$ \le$1, 000, 000 . No two lands have the same deliciousness. Two bamboo lands can be so close that they can be regarded as at the same point.

Output 

For each test case, print the case number followed by the number of days Jingjing can survive. Look at the output for sample input for details.

Sample Input 

2
3
0 0 3 4
2 2 2 3
5 5 1 3
3
0 0 3 4 
2 2 2 3
5 5 1 3

Sample Output 

Case 1: 2
Case 2: 2
思路:对坐标轴进行变换,这样就可以根据给定的距离范围进行查询,如果两个点的距离(题目中给定的计算公式)小于l,那么两个点对应的x,y的差得差得绝对值小于l,并且和的差得绝对值小于等于l,这是进行转化的依据,然后二维线段树,因为节点太多,可以用动态线段树

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
const int INF=1000000000;
int N;

struct node
{
    int x,y,l,w,id;
    bool operator<(const node &A)const
    {
        return w<A.w;
    }
}a[maxn];
int dp[maxn];
int tot;
int minx,miny,maxx,maxy;
struct IntervalTree
{
    int maxv[maxn*70];
    int root[maxn<<2];
    int ch[maxn*70][2];
    void build()
    {
        tot=0;
        memset(root,0,sizeof(root));
        memset(maxv,0,sizeof(maxv));
    }
    void update2(int &rt,int l,int r,int pos,int val)
    {
        if(!rt)
        {
            rt=++tot;
            ch[rt][0]=ch[rt][1]=0;
            maxv[rt]=0;
        }
        if(l==r)
        {
            maxv[rt]=max(maxv[rt],val);
            return ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)update2(ch[rt][0],l,mid,pos,val);
        else update2(ch[rt][1],mid+1,r,pos,val);
        pushup(rt);
    }
    void update(int o,int l,int r,int x,int y,int val)
    {
        update2(root[o],miny,maxy,y,val);
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(x<=mid)update(o<<1,l,mid,x,y,val);
        else update(o<<1|1,mid+1,r,x,y,val);

    }
    void pushup(int rt)
    {
        maxv[rt]=max(maxv[ch[rt][0]],maxv[ch[rt][1]]);
    }
    int query2(int &rt,int l,int r,int q1,int q2)
    {
        if(!rt)return 0;
        if(q1<=l&&r<=q2)return maxv[rt];
        int mid=(l+r)>>1;
        int ans=0;
        if(q1<=mid)ans=max(ans,query2(ch[rt][0],l,mid,q1,q2));
        if(q2>mid) ans=max(ans,query2(ch[rt][1],mid+1,r,q1,q2));
        return ans;
    }
    int query(int o,int l,int r,int qx1,int qx2,int qy1,int qy2)
    {
        if(qx1<=l&&r<=qx2)
        {
            return query2(root[o],miny,maxy,qy1,qy2);
        }
        int mid=(l+r)>>1;
        int ans=0;
        if(qx1<=mid)ans=max(ans,query(o<<1,l,mid,qx1,qx2,qy1,qy2));
        if(qx2>mid)ans=max(ans,query(o<<1|1,mid+1,r,qx1,qx2,qy1,qy2));
        return ans;
    }
}tree;
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
        minx=INF,miny=INF,maxx=-INF,maxy=-INF;
        for(int i=1;i<=N;i++)
        {
            scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].w,&a[i].l);
            a[i].id=i;
            int x=a[i].x,y=a[i].y;
            a[i].x=x-y,a[i].y=x+y;
            minx=min(a[i].x,minx);
            miny=min(a[i].y,miny);
            maxx=max(maxx,a[i].x);
            maxy=max(maxy,a[i].y);
        }
        tree.build();
        sort(a+1,a+1+N);
        for(int i=1;i<=N;i++)
        {
            int res=tree.query(1,minx,maxx,a[i].x-a[i].l,a[i].x+a[i].l,a[i].y-a[i].l,a[i].y+a[i].l)+1;
            dp[a[i].id]=res;
            tree.update(1,minx,maxx,a[i].x,a[i].y,res);
        }
        int ans=1;
        for(int i=1;i<=N;i++)ans=max(ans,dp[i]);
        printf("Case %d: %d\n",cas++,ans);
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值