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

被折叠的 条评论
为什么被折叠?



