hdu5517 二维线段树

来源:互联网 发布:nike跑步软件下载 编辑:程序博客网 时间:2024/06/06 02:33

题意:N个二元组《a,b》,M个三元组《c,d,e》,当b==e时,构成《a,c,d》,让后当不存在<u,v,w>,(u>=a,v>=b,w>=c),问存在几个元素。

思路:自己写一点都不会,题都看不懂。

首先基本思路是对于(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 <iostream>#include <algorithm>#include <cstdio>#include <cmath>#include <cstring>#include <string>#define lowbit(x) (x&-x)typedef long long ll;typedef long long LL;using namespace std;const int INF=0x3f3f3f3f;const int MAXN=1010;int f[MAXN][MAXN];int zhi[MAXN][MAXN];int val[MAXN*100];int num[MAXN*100];ll sum[MAXN][MAXN];int main(){    int T;    cin>>T;    int cas = 1;    while(T--)    {        memset(f,-1,sizeof(f));        memset(zhi,-1,sizeof(zhi));        memset(num,0,sizeof(num));        memset(val,0,sizeof(val));        memset(sum,0,sizeof(sum));        int n,m;        cin>>n>>m;        int x,y,z;        while(n--)        {            scanf("%d%d",&x,&y);            if(val[y]>x)                continue;            if(val[y]==x)                num[y]++;            if(val[y]<x)            {                val[y] = x;                num[y] = 1;            }        }        while(m--)        {            scanf("%d%d%d",&x,&y,&z);            if(val[z]==0)                continue;            if(zhi[x][y]>val[z])                continue;            if(zhi[x][y]==val[z])                sum[x][y]+=num[z];            if(zhi[x][y]<val[z])            {                sum[x][y] = num[z];                zhi[x][y] = val[z];            }        }                ll ans = 0;        for(int i=1000;i>0;i--)            for(int j=1000;j>0;j--)            {                f[i][j] = max(f[i+1][j],f[i][j+1]);                if(f[i][j]<zhi[i][j])                    ans+=sum[i][j];                f[i][j]  =max(f[i][j],zhi[i][j]);            }        printf("Case #%d: %lld\n",cas++,ans);    }    return 0;}

#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;}