https://blog.youkuaiyun.com/DERITt/article/details/51201535
对于二元组(a,b),b相同的话只有最大的a值有效,所以对相同的b记录一下最大值的个数。
对于三元组(c,d,e),对于相同的e,先按照c排序,对于c相同的三元组,只有最大的d有效,对于c不同的三元组,一个三元组的(c,d,e)有效的话,只有它的d只大于所有c值比它大的三元组的d值,所以扫一遍记录最大值就能知道哪些三元组有效。最后得到很多拼接成的三元组(a,c,d)和它们个数,按第一维排序扫一遍,用树状数组记录最大值就能nlogn搞了
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)
.
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
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
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 5;
typedef long long ll;
#define lowbit(x) ((x)&(-x))
struct Point {
int x, y, z;
ll w;
Point(int x = 0, int y = 0, int z = 0, ll w = 0): x(x), y(y), z(z), w(w) {}
bool operator < (const Point& u) const {
if (x != u.x) return x < u.x;
if (y != u.y) return y < u.y;
return z < u.z;
}
bool operator == (const Point& u) const { return !((*this)<u || u<(*this)); }
};
int N, M, T[maxn], C[maxn];
Point P[maxn];
void init () {
scanf("%d%d", &N, &M);
memset(T, 0, sizeof(T));
int a, b, c;
for (int i = 0; i < N; i++) {
scanf("%d%d", &a, &b);
if (a > T[b]) { T[b] = a, C[b] = 0; }
if (a == T[b]) C[b]++;
}
int n = 0;
for (int i = 0; i < M; i++) {
scanf("%d%d%d", &a, &b, &c);
if (T[c])
P[n++] = Point(T[c], a, b, C[c]);
}
sort(P, P + n);
N = 0;
for (int i = 1; i < n; i++) {
if (P[i] == P[N]) P[N].w += P[i].w;
else P[++N] = P[i];
}
}
ll fenw[1005][1005];
void add(int x, int y, ll v) {
for (int i = x; i <= 1000; i += lowbit(i)) {
for (int j = y; j <= 1000; j += lowbit(j))
fenw[i][j] += v;
}
}
ll sum(int x, int y) {
int ret = 0;
for (int i = x; i; i -= lowbit(i)) {
for (int j = y; j; j -= lowbit(j))
ret += fenw[i][j];
}
return ret;
}
ll query(int x1, int y1, int x2, int y2) {
return sum(x2, y2) - sum(x2, y1-1) - sum(x1-1, y2) + sum(x1-1, y1-1);
}
ll solve () {
ll ans = 0;
memset(fenw, 0, sizeof(fenw));
for (int i = N; i >= 0; i--) {
if (!query(P[i].y, P[i].z, 1000, 1000))
ans += P[i].w;
add(P[i].y, P[i].z, 1);
}
return ans;
}
int main () {
int cas;
scanf("%d", &cas);
for (int kcas = 1; kcas <= cas; kcas++) {
init();
printf("Case #%d: %lld\n", kcas, solve());
}
return 0;
}