HDU 5517 (二維樹狀陣列)
阿新 • • 發佈:2019-01-11
題意:給出一個pair(a,b)集合A,triple(c,d,e)集合B,然後如果b和e相等可以把新的triple(a,c,d)扔到集合C.求C中的(a,b,c)個數使得C中不存在(u,v,e)滿足
顯然對於相等的b只用保留最大的a,然後記錄下這個最大的a的個數.然後對於B中一個triple,就只產生一種C中的triple.等C都求出來以後把相同的triple數量加起來.最後按照a排序,樹狀陣列維護b,c就好了.
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#define Clear(x,y) memset (x,y,sizeof(x))
#define FOR(a,b,c) for (int a = b; a <= c; a++)
#define REP(a,b,c) for (int a = b; a >= c; a--)
#define fi first
#define se second
#define pii pair<int, int>
#define pli pair<long long, int>
#define pb push_back
#define mod 1000000007
template <class T>
inline bool scan (T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return 0; //EOF
while (c != '-' && (c < '0' || c > '9') ) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0' );
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
using namespace std;
#define maxn 1005
#define maxm 100005
struct node {
int a, b, c; long long num;
bool operator < (const node &aa) const {
if (a != aa.a) return a < aa.a;
if (b != aa.b) return b < aa.b;
return c < aa.c;
}
bool operator == (const node &aa) const {
return a == aa.a && b == aa.b && c == aa.c;
}
};
vector <int> a[maxm];
vector <pii> A[maxm];
vector <node> p; node gg[maxm]; int cnt;
int c[maxn][maxn];
int n, m;
int lowbit (int x) {
return x&(-x);
}
void add (int x, int y) {
for (int i = x; i > 0; i -= lowbit (i)) {
for (int j = y; j > 0; j -= lowbit (j)) {
c[i][j]++;
}
}
}
int query (int x, int y) {
int ans = 0;
for (int i = x; i <= 1000; i += lowbit (i)) {
for (int j = y; j <= 1000; j += lowbit (j)) {
ans += c[i][j];
}
}
return ans;
}
int main () {
//freopen ("more.in", "r", stdin);
int t, kase = 0;
scanf ("%d", &t);
while (t--) {
printf ("Case #%d: ", ++kase);
scanf ("%d%d", &n, &m);
for (int i = 1; i < maxm; i++) {
a[i].clear ();
A[i].clear ();
}
for (int i = 1; i <= n; i++) {
int x, y; scan (x), scan (y);
a[y].push_back (x);
}
for (int i = 1; i <= 100000; i++) if (a[i].size ()) {
int sz = a[i].size ();
int Max = 0, num = 0;
for (int j = 0; j < sz; j++) {
if (a[i][j] == Max) num++;
else if (a[i][j] > Max) {
Max = a[i][j];
num = 1;
}
}
A[i].push_back (make_pair (Max, num));//b值相等的<a,b>只保留最大的a並記錄個數
}
p.clear ();
for (int i = 1; i <= m; i++) {
int x, y, z; scan (x), scan (y), scan (z);
if (A[z].size ()) {
pii tmp = A[z][0];
p.pb ((node) {tmp.fi, x, y, tmp.se});
}
}
sort (p.begin (), p.end ()); int sz = p.size ();
cnt = 0;
for (int i = 0; i < sz; i++) {
if (!i || !(p[i] == p[i-1])) {
gg[cnt++] = p[i];
}
else {
gg[cnt-1].num += p[i].num;
}
}//挖出所有的三元組 合併相同的
Clear (c, 0);//二維樹狀陣列
long long ans = 0;
for (int i = cnt-1; i >= 0; i--) {
int tmp = query (gg[i].b, gg[i].c);
if (!tmp) ans += gg[i].num;
add (gg[i].b, gg[i].c);
}
printf ("%lld\n", ans);
}
return 0;
}