hdu 5517(二维树状数组)

本文介绍了一种高效算法,用于解决大规模数据集上的凸点对问题。通过优化数据结构和算法设计,能够在有限时间内准确计算出特定条件下不存在更优解的元素对数量。

Given the finite multi-set AA of nn pairs of integers, an another finite multi-set BB of mm triples of integers, we define the product of AA and BB as a multi-set

C=A∗B={⟨a,c,d⟩∣⟨a,b⟩∈A, ⟨c,d,e⟩∈B and b=e}C=A∗B={⟨a,c,d⟩∣⟨a,b⟩∈A, ⟨c,d,e⟩∈B and b=e}

For each ⟨a,b,c⟩∈C⟨a,b,c⟩∈C, its BETTER set is defined as

BETTERC(⟨a,b,c⟩)={⟨u,v,w⟩∈C∣⟨u,v,w⟩≠⟨a,b,c⟩, u≥a, v≥b, w≥c}BETTERC(⟨a,b,c⟩)={⟨u,v,w⟩∈C∣⟨u,v,w⟩≠⟨a,b,c⟩, u≥a, v≥b, w≥c}

As a \textbf{multi-set} of triples, we define the TOP subset (as a multi-set as well) of CC, denoted by TOP(C)TOP(C), as

TOP(C)={⟨a,b,c⟩∈C∣BETTERC(⟨a,b,c⟩)=∅}TOP(C)={⟨a,b,c⟩∈C∣BETTERC(⟨a,b,c⟩)=∅}

You need to compute the size of TOP(C)TOP(C).
Input
The input contains several test cases. The first line of the input is a single integer t (1≤t≤10)t (1≤t≤10) which is the number of test case. Then tt test cases follow.

Each test case contains three lines. The first line contains two integers n (1≤n≤105)n (1≤n≤105) and m (1≤m≤105)m (1≤m≤105) corresponding to the size of AA and BB respectively.
The second line contains 2×n2×n nonnegative integers
a1,b1,a2,b2,⋯,an,bn
a1,b1,a2,b2,⋯,an,bn

which describe the multi-set AA, where 1≤ai,bi≤1051≤ai,bi≤105.
The third line contains 3×m3×m nonnegative integers
c1,d1,e1,c2,d2,e3,⋯,cm,dm,em
c1,d1,e1,c2,d2,e3,⋯,cm,dm,em

corresponding to the mm triples of integers in BB, where 1≤ci,di≤1031≤ci,di≤103 and 1≤ei≤1051≤ei≤105.
Output
For each test case, you should output the size of set TOP(C)TOP(C).
Sample Input
2
5 9
1 1 2 2 3 3 3 3 4 2
1 4 1 2 2 1 4 1 1 1 3 2 3 2 2 4 1 2 2 4 3 3 2 3 4 1 3
3 4
2 7 2 7 2 7
1 4 7 2 3 7 3 2 7 4 1 7
Sample Output
Case #1: 5
Case #2: 12

题意:给你 n对 a,b m对 c,d,e;
当 b ==e 可以组成 Cmultiset < a,c,d > 问有多少对 a,c,d 不存在任何一组 u,v,w 属于C 同时u!=a&&v!=c&&w!=d, u>=a&&v>=c&&w>=d, 就是找凸点,
由于n,m 这两个集合数据量达到了1e5,组合起来能达到1e10,单纯存起来肯定不行,所以在集合A 我们只需要保留每个b的最大值a即可,这样 对于 相同的c,d我们只需要保留最大的a,顺便存下和最大值相等的数量,然后排序,把相同的P数量合并。接下来就是,比较简单的其中一维d,按照从大到小排序,其他的进行二维树状数组就好。就是看 以前的a比当前a大的那些,有没有满足 v>=c&&w>=d,如果没有证明这个点是合法的,否则就是不合法的,因为a比它小的点本来就是不合法的。

#include <bits/stdc++.h>
using namespace std;
const int N =1e5+10;
typedef long long ll;
#define lowbit(x) ((x)&(-x))
ll c[1010][1010];
struct P{
    int a,c,d;
    ll num;
    P(){}
    P(int _a,int _c,int _d,int _num):a(_a),c(_c),d(_d),num(_num){}
    bool operator == (const P &rhs) const {
        if(a==rhs.a&&c==rhs.c&&d==rhs.d) return 1;
        return 0;
    }
}p[N];

int cmp(P a,P b)
{
    if(a.a!=b.a) return a.a<b.a;
    if(a.c!=b.c) return a.c<b.c;
    if(a.d!=b.d) return a.d<b.d;
    return a.num<b.num;
}

int cnt[N],idl[N];

void update(int x,int y,int val)
{
    int i,k;
    for(i=x;i<=1000;i+=lowbit(i))
    {
        for(k=y;k<=1000;k+=lowbit(k))
            c[i][k]+=val;
    }
}

ll Get(int x,int y)
{
    int i,k;
    ll sum=0;
    for(i=x;i>0;i-=lowbit(i))
    {
        for(k=y;k>0;k-=lowbit(k))
            sum+=c[i][k];
    }
    return sum;
}

ll query(int x1,int y1,int x2,int y2)
{
    return Get(x1,y1)-Get(x2-1,y1)-Get(x1,y2-1)+Get(x2-1,y2-1);
}


int main()
{
    int t;
    scanf("%d",&t);
    int cas=1;
    while(t--)
    {
        memset(c,0,sizeof(c));
        memset(idl,0,sizeof(idl));
        memset(cnt,0,sizeof(cnt));
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if(a>idl[b])
               idl[b]=a,cnt[b]=1;
            else if(a==idl[b])
                cnt[b]++;
        }
        for(int i=1;i<=m;i++)
        {
            int c,d,e;
            scanf("%d%d%d",&c,&d,&e);
            p[i]=P(idl[e],c,d,cnt[e]);
        }

        sort(p+1,p+m+1,cmp);
        int tot=0;
        for(int i=1;i<=m;i++)
        {
            if(p[tot]==p[i]) p[tot]=P(p[tot].a,p[tot].c,p[tot].d,p[tot].num+p[i].num);
            else p[++tot]=p[i];
        }
        ll sum=0;
        for(int i=tot;i>=1;i--)
        {
            if(!query(1000,1000,p[i].c,p[i].d)) sum+=p[i].num;
            update(p[i].c,p[i].d,p[i].num); 
        }
        printf("Case #%d: %lld\n",cas++,sum );
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值