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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值