Triple
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1127 Accepted Submission(s): 403
Problem Description
Given the finite
multi-set
A
of
n
pairs of integers, an another finite
multi-set
B
of
m
triples of integers, we define the product of
A
and
B
as a
multi-set
C=A∗B
={⟨a,c,d⟩∣⟨a,b⟩∈A, ⟨c,d,e⟩∈B and b=e}![]()
For each ⟨a,b,c⟩∈C
, its BETTER set is defined as
BETTER
C
(⟨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 C
, denoted by
TOP(C)
, as
TOP(C)={⟨a,b,c⟩∈C∣BETTER
C
(⟨a,b,c⟩)=∅}
You need to compute the size of TOP(C)
.
C=A∗B
For each ⟨a,b,c⟩∈C
BETTER
As a \textbf{multi-set} of triples, we define the TOP subset (as a multi-set as well) of C
TOP(C)={⟨a,b,c⟩∈C∣BETTER
You need to compute the size of TOP(C)
Input
The input contains several test cases. The first line of the input is a single integer
t (1≤t≤10)
which is the number of test case. Then
t
test cases follow.
Each test case contains three lines. The first line contains two integers n (1≤n≤10
5
)
and
m (1≤m≤10
5
)
corresponding to the size of
A
and
B
respectively.
The second line contains 2×n
nonnegative integers
which describe the multi-set A
, where
1≤a
i
,b
i
≤10
5![]()
.
The third line contains 3×m
nonnegative integers
corresponding to the m
triples of integers in
B
, where
1≤c
i
,d
i
≤10
3![]()
and
1≤e
i
≤10
5![]()
.
Each test case contains three lines. The first line contains two integers n (1≤n≤10
The second line contains 2×n
a
1
,b
1
,a
2
,b
2
,⋯,a
n
,b
n![]()
which describe the multi-set A
The third line contains 3×m
c
1
,d
1
,e
1
,c
2
,d
2
,e
3
,⋯,c
m
,d
m
,e
m![]()
corresponding to the m
Output
For each test case, you should output the size of set
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
Source
Recommend
wange2014
题意:
给了n个二元集<a,b>和m个三元集<c,d,e>。给出了构造另一个元集合的方法,当b==e时构造成三元集C={<a,c,d>}。求top(C)集合。
思路:
第一:当e相同的时候,若可构造多个集合<a1,b,c>,<a2,b,c>...<an,b,c>则取<max(a1,a2,...an)>这个集合。因为小于最大值的都会被舍弃。
第二:去除它的重点。用一个cnt来记录它的重点的个数。为了方便后面的计算。
第三:可以将a,b,c依次按降序来排,然后从后往前面遍历。由b和c构成一个二维平面,每次加点之前看它的右上区域是否还有点,如果有点则该点有Better集合,所以不能加。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int a[100005];
int cnt[100005];
int tr[1005][1005];
int lowbit(int i)
{
return i&(-i);
}
void update(int x,int y,int n)
{
for(int i=x;i<=n;i+=lowbit(i))
{
for(int j=y;j<=n;j+=lowbit(j))
{
tr[i][j]++;
}
}
}
int query(int x,int y)
{
int sum=0;
for(int i=x;i>0;i-=lowbit(i))
{
for(int j=y;j>0;j-=lowbit(j))
{
sum+=tr[i][j];
}
}
return sum;
}
struct node
{
int a,b,c,cnt;
node()
{
cnt=0;
}
}q[100005];
bool cmp(node a,node b)
{
if(a.a!=b.a)
return a.a<b.a;
else if(a.b!=b.b)
return a.b<b.b;
else
return a.c<b.c;
}
int main()
{
int t,n,m,x,y,z,cas=1;
scanf("%d",&t);
while(t--)
{
memset(a,0,sizeof(a));
memset(cnt,0,sizeof(cnt));
memset(tr,0,sizeof(tr));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
if(a[y]==0)
{
a[y]=x;
cnt[x]=1;
}
else
{
if(x>a[y])
{
a[y]=x;
cnt[x]=1;
}
else if(x==a[y])
cnt[x]++;
}
}
int p=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
if(cnt[a[z]]==0)
continue;
else
{
q[p].a=a[z];
q[p].b=x;
q[p].c=y;
q[p].cnt=cnt[a[z]];
p++;
}
}
sort(q,q+p,cmp);
int k=0;
for(int i=1;i<p;i++)
{
if(q[k].a==q[i].a&&q[k].b==q[i].b&&q[k].c==q[i].c)
{
q[k].cnt+=q[i].cnt;
}
else
{
q[++k]=q[i];
}
}
int ans=0;
for(int i=k;i>=0;i--)
{
int num=query(1001,1001)-query(1001,q[i].c-1)-query(q[i].b-1,1001)+query(q[i].b-1,q[i].c-1);
if(num==0) ans+=q[i].cnt;
update(q[i].b,q[i].c,1001);
}
printf("Case #%d: %d\n",cas++,ans);
}
return 0;
}