1. 程式人生 > >HDU 5517 (二維樹狀陣列)

HDU 5517 (二維樹狀陣列)

題意:給出一個pair(a,b)集合A,triple(c,d,e)集合B,然後如果b和e相等可以把新的triple(a,c,d)扔到集合C.求C中的(a,b,c)個數使得C中不存在(u,v,e)滿足{(a,b,c)(u,v,e),au,bv,ce}.

顯然對於相等的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; }