HDU 5517 二维树状数组

来源:互联网 发布:淘宝违规申诉入口 编辑:程序博客网 时间:2024/05/24 06:04
HDU 5517 
题目链接: 
http://acm.hdu.edu.cn/showproblem.php?pid=5517 
题意: 
有二元组(a,b),三元组(c,d,e)。当b == e时它们能构成(a,c,d)。 
然后,当不存在(u,v,w)!=(a,b,c)且u>=a,v>=b,w>=c时,则是一个better集合里的元素。 
问这个better集合有几个元素。 
思路: 
自己写的时候完全没有思路啊~ 
参考了http://async.icpc-camp.org/d/227-shenyang-2015-i 
http://blog.csdn.net/keshuai19940722/article/details/49583149 
首先基本思路是对于(a1,b1),(a2,b2),当b1==b2时,只留a最大的那个。 
同理(c,d,e),当c、e相同时只留d最大的那个。 
因为e必须要和b相同才能拼接成三元组,所以遍历输入(c,d,e)时就能把有效的(c,d,e)记录下来形成(a,d,e). 

然后要去重和不合法的(a,d,e)。按a从大到小排序,用二位树状数组统计在平面直角坐标上x >= d和y>=e的地方是否出现过(a,d,e),没出现过即合法。 


#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <queue>#include <algorithm>#include <iostream>#include <vector>using namespace std;#define LL long longconst int MAXN = 1e5 + 5;int id1[MAXN], cnt1[MAXN];struct P{    int c, d, e;    LL v;    P(){}    P(int _c, int _d, int _e, LL _v){c = _c, d = _d, e = _e,v = _v;}    bool operator == (const P &rbs)const    {        if(c == rbs.c && d == rbs.d && e == rbs.e)  return true;        return false;    }}p[MAXN];bool cmp1(P u, P v){    if(u.c != v.c)  return u.c < v.c;    if(u.d != v.d)  return u.d < v.d;    return u.e < v.e;}const int MAXM = 1000 + 5;int tree[MAXM][MAXM];int lowbit(int a){    return a & -a;}void add(int x, int y, int val){    for(int i = x ; i <= 1000 ; i += lowbit(i)){        for(int j = y ; j <= 1000 ; j+= lowbit(j))            tree[i][j] += val;    }}LL sum(int x, int y){    LL ans = 0;    for(int i = x ; i > 0 ; i -= lowbit(i)){        for(int j = y ; j > 0 ; j -= lowbit(j)){            ans += tree[i][j];        }    }    return ans;}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);}int main(){//    freopen("HDU 5517.in", "r", stdin);    int T;    scanf("%d", &T);    for(int cas = 1 ; cas <= T ; cas++){        int n, m;        scanf("%d%d", &n, &m);        memset(id1, -1, sizeof(id1));        int a, b, c;        for(int i = 1 ; i <= n ; i++){            scanf("%d%d", &a, &b);            if(id1[b] < a){                id1[b] = a;                cnt1[b] = 1;            }            else if(id1[b] == a)    cnt1[b]++;        }        int num = 0;        for(int i = 0 ; i < m ; i++){            scanf("%d%d%d", &a, &b, &c);            if(id1[c] != -1){                p[num++] = P(id1[c], a, b, cnt1[c]);            }        }        sort(p, p + num, cmp1);        n = 0;        for(int i = 1 ; i < num ; i++){            if(p[n] == p[i]){                p[n].v += p[i].v;            }            else    p[++n] = p[i];        }//        for(int i = 0 ; i < n ; i++)//            printf("i = %d, c = %d, d = %d, e = %d\n", i, p[i].c, p[i].d, p[i].e);        memset(tree, 0, sizeof(tree));        LL ans = 0;        for(int i = n ; i >= 0 ; i--){            if(!query(p[i].d, p[i].e, 1000, 1000))   ans += p[i].v;            add(p[i].d, p[i].e, 1);        }        printf("Case #%d: %I64d\n", cas, ans);    }    return 0;}


原创粉丝点击