Triple
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 571 Accepted Submission(s): 204
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
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 C , denoted by TOP(C) , as
TOP(C)={⟨a,b,c⟩∈C∣BETTERC(⟨a,b,c⟩)=∅}
You need to compute the size of TOP(C) .
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
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 C , denoted by TOP(C) , as
TOP(C)={⟨a,b,c⟩∈C∣BETTERC(⟨a,b,c⟩)=∅}
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≤105) and m (1≤m≤105) 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≤ai,bi≤105 .
The third line contains 3×m nonnegative integers
corresponding to the m triples of integers in B , where 1≤ci,di≤103 and 1≤ei≤105 .
Each test case contains three lines. The first line contains two integers n (1≤n≤105) and m (1≤m≤105) corresponding to the size of A and B respectively.
The second line contains 2×n nonnegative integers
a1,b1,a2,b2,⋯,an,bn
which describe the multi-set A , where 1≤ai,bi≤105 .
The third line contains 3×m nonnegative integers
c1,d1,e1,c2,d2,e3,⋯,cm,dm,em
corresponding to the m triples of integers in B , where 1≤ci,di≤103 and 1≤ei≤105 .
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
题意:
给出n个二元组<a,b>和m个三元组<c,d,e>现在将其组合成一个新的三元组集合,新三元组中允许有重复元素,一个二元组和一个三元组可以组合当且仅当b==e时将其组合成<a,c,d>,在新组合的三元组中任取一元素<a,b,c>,如果在新组合存在一个元素<u,v,w>使得u!=a && v!=b && w!=c 同时 u>=a && v>=b &&w>=c 则元素<a,b,c>不统计在答案的集合中,否则统计在答案的集合中,问最终答案的集合中有多少元素,可以有重复元素。
要点:
1.如果b相同,取最大的a,这个只需要用数组实现即可。
2.对于相同的元素定义一个权值表示数量。
3.由于b只有和e相同时才能构成新元素,所以集合里最多有1e5个元素,因为每一个e最多对应一个b,一个b对应一个a。
4.二维树状数组处理的是一个矩阵,插入元素时,按a从大到小,在此基础上按c再按d从大到小排序(或先d后c)
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s) memset(a,x,(s)*sizeof a[0])
#define mem(a,x) memset(a,x,sizeof a)
#define ysk(x) (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxN= 1e5+0.5 ;
int N,M;
int num[maxN+5],maxa[maxN+5];
int n2,kase=0;
struct Point
{
int a,c,d,w;
Point(){}
Point(int a,int c,int d,int w):a(a),c(c),d(d),w(w){}
bool operator<(const Point i)const
{
if(a!=i.a) return a<i.a;
if(c!=i.c) return c<i.c;
return d<i.d;
}
bool operator==(const Point i)const
{
return a==i.a&&c==i.c&&d==i.d;
}
}p[maxN+10];
struct BitTree
{
int n,C[1003][1003];
void init()
{
mem(C,0);
n=1000;
}
void update(int x,int y)
{
for(int i=x;i<=n;i+=i&(-i))
{
for(int j=y;j<=n;j+=j&(-j) )
{
C[i][j]++;
}
}
}
int query(int x,int y)
{
int ans=0;
for(int i=x;i;i-=i&(-i))
{
for(int j=y;j;j-=j&(-j))
{
ans+=C[i][j];
}
}
return ans;
}
int cal(int x,int y)
{
return query(1000,1000)-query(1000,y-1)-query(x-1,1000)+query(x-1,y-1);
}
}bt;
void init()
{
int a,b,c,d;
mem(maxa,0);
mem(num,0);
for0(i,N)
{
cin>>a>>b;
if(a>maxa[b])
{
maxa[b]=a;
num[b]=1;
}
else if(a==maxa[b])
{
num[b]++;
}
}
n2=0;
for0(i,M)
{
cin>>c>>d>>b;
if(!num[b]) continue;
p[n2++]=Point(maxa[b],c,d,num[b]);
}
sort(p,p+n2);
int n3=0;
for(int i=1;i<n2;i++)
{
if(p[i]==p[n3]) p[n3].w+=p[i].w;
else p[++n3]=p[i];
}
n2=n3;
}
void solve()
{
bt.init();
ll ans=0;
for(int i=n2;i>=0;i--)
{
if(!bt.cal(p[i].c,p[i].d )) ans+=p[i].w;
bt.update(p[i].c,p[i].d);
}
printf("Case #%d: %lld\n",++kase,ans);
}
int main()
{
std::ios::sync_with_stdio(false);kase=0;
int T;cin>>T;
while(T--)
{
cin>>N>>M;
init();
solve();
}
return 0;
}