2015ACM/ICPC亚洲区沈阳站 HDU 5517 Triple (二维线段树)

题意 :略

首先我们先假设出a1,b1和a2,b2分别为(1,2),和(2,2)。那么我们发现,其实(1,2)对于答案是根本没有贡献的。

所以对于b相同的,取a最大的即可。

首先我们定义一个矩阵Map[N][N],Map[c'][d']代表当c=c',d=d'的时候,a所能取到的最大值。

那么对于一个点c',d'假如任何的(c''>=c'&&d''>=d'(不包括点(c',d'))如果都没有Map[c''][d'']都小于Map[c'][d'],则这个点是对答案有贡献的。

因为相同的点可能不止一个,所以我们可以开一个辅助矩阵来存储

我们可以用二维线段树来进行查询。

这个问题便解决了

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define llson j<<1,l,mid
#define rrson j<<1|1,mid+1,r
#define maxn 1010
typedef long long ll;
using namespace std;
ll Map[maxn][maxn],Max[maxn*4][maxn*4];
ll fange[maxn][maxn];
ll n,q,t,ans;

void pushup(ll i,ll j)
{
    Max[i][j]=max(Max[i][j<<1],Max[i][j<<1|1]);
}
void build_y(ll i,ll u,ll j,ll l,ll r)
{
    if(l==r)
    {
        Max[i][j]=Map[u][l];
        return ;
    }
    ll mid=(l+r)>>1;
    build_y(i,u,llson);build_y(i,u,rrson);
    pushup(i,j);
}
void build_x(ll i,ll l,ll r)
{
    if(l==r)
    {
        build_y(i,l,1,1,n);
        return ;
    }
    ll mid=(l+r)>>1;
    build_x(lson);build_x(rson);
}
ll query_y(ll i,ll j,ll l,ll r,ll y1,ll y2)
{
    if(l==y1&&y2==r) return Max[i][j];
    ll mid=(l+r)>>1;
    if(y2<=mid) return query_y(i,llson,y1,y2);
    else if(y1>mid) return query_y(i,rrson,y1,y2);
    else return max(query_y(i,llson,y1,mid),query_y(i,rrson,mid+1,y2));
}
void query_x(ll i,ll l,ll r,ll x1,ll x2,ll y1,ll y2)
{
    if(l==r)
    {
        ans=max(ans,query_y(i,1,1,n,y1,y2));
        return ;
    }
    ll mid=(l+r)>>1;
    if(x1<=mid) query_x(lson,x1,x2,y1,y2);
    if(x2>mid) query_x(rson,x1,x2,y1,y2);
}
struct NODE
{
    ll x,y,val;
}a[100010],b[100010];
bool cmp(NODE a,NODE b)
{
    return a.val<b.val;
}
int main()
{
    ll T;
    ll n1,m1,i,j,i1=1;
//    freopen("in.txt","r",stdin);
    scanf("%lld",&T);
    n=1000;
    while(T--)
    {
        memset(Map,0,sizeof(Map));
        memset(fange,0,sizeof(fange));
        scanf("%lld%lld",&n1,&m1);
        for(i=1;i<=n1;i++)
            scanf("%lld%lld",&a[i].x,&a[i].val);
        for(i=1;i<=m1;i++)
            scanf("%lld%lld%lld",&b[i].x,&b[i].y,&b[i].val);
        sort(a+1,a+1+n1,cmp);
        sort(b+1,b+1+m1,cmp);
        i=1;j=1;
        ll tmp=0;
        ll time=1;
        for(i=1;i<=n1;i++)
        {
            tmp=a[i].x;time=1;
            while(i+1<=n1&&a[i].val==a[i+1].val)
            {
                if(tmp<a[i+1].x)
                {
                    tmp=a[i+1].x;
                    time=1;
                }
                else if(tmp==a[i+1].x)
                {
                    time++;
                }
                i++;
            }
            while(j<=m1&&b[j].val<=a[i].val)
            {
                if(b[j].val==a[i].val)
                {
                    if(Map[b[j].x][b[j].y]<tmp)
                    {
                        Map[b[j].x][b[j].y]=tmp;
                        fange[b[j].x][b[j].y]=time;
                    }
                    else if(Map[b[j].x][b[j].y]==tmp)
                    {
                        fange[b[j].x][b[j].y]+=time;
                    }
                }
                j++;
            }
        }
        ll answer=0;
        build_x(1,1,n);
        for(i=1;i<=1000;i++)
            for(j=1;j<=1000;j++)
            {
                if(i==1000&&j==1000)
                {
                    answer+=fange[i][j];
                    continue;
                }
                else if(i==1000)
                {
                    if(fange[i][j])
                    {
                        ans=0;
                        query_x(1,1,n,i,n,j+1,n);
                        if(ans<Map[i][j])
                            answer+=fange[i][j];
                    }
                }
                else if(j==1000)
                {
                    if(fange[i][j])
                    {
                        ans=0;
                        query_x(1,1,n,i+1,n,j,n);
                        if(ans<Map[i][j])
                            answer+=fange[i][j];
                    }
                }
                else if(fange[i][j])
                {
                    ans=0;
                    query_x(1,1,n,i+1,n,j,n);
                     if(ans<Map[i][j])
                    {
                        ans=0;
                        query_x(1,1,n,i,n,j+1,n);
                        if(ans<Map[i][j])
                        {
                            answer+=fange[i][j];
                        }
                    }
                }
            }
        printf("Case #%lld: ",i1++);
        printf("%lld\n",answer);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值