hdu 5517 Triple(二维树状数组)

HDU 5517

题目:给出一种有三个元素的顺序,这个数据定义一种偏序,当且仅当一个三元数的所有元素都大于等于另一个时这个数比另一个大.求这个一个集合中不比任何数小的三元数有多少个.

思路:首先排序去重,此时第一维有序,不用考虑,然后只有不存在比当前数的另外两维都大的数时当前数是可选的,用二位树装数组维护这个信息即可.

/*
* @author:  Cwind
*/
#include <bits/stdc++.h>

using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-4)
#define INF (1000000300)
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;

const int maxn=1e5+400;
struct tri{
    int a,b,c;
    ll cnt;
    tri(int a,int b,int c,ll cnt):a(a),b(b),c(c),cnt(cnt){}
    tri(){}
    bool operator < (const tri &C)const{
        if(a!=C.a) return a>C.a;
        if(b!=C.b) return b>C.b;
        return c>C.c;
    }
    bool operator != (const tri &C)const{
        return !(a==C.a&&b==C.b&&c==C.c);
    }
};
const int maxv=1005;
struct BIT2D{
    int a[maxv][maxv];
    void add(int x,int y){
        for(;x<maxv;x+=x&-x)
            for(int i=y;i<maxv;i+=i&-i) a[x][i]++;
    }
    int sum(int x,int y){
        int ans=0;
        for(;x>0;x-=x&-x)
            for(int i=y;i>0;i-=i&-i) ans+=a[x][i];
        return ans;
    }
    void clear(){clr(a);}
}B;
tri ans[maxn];
int h;
int t;
int n,m;
P A[maxn];
void init(){
    clr(A);B.clear();
    h=0;
}
int cas;
int main(){
    freopen("/home/slyfc/CppFiles/in","r",stdin);
    //freopen("/home/slyfc/CppFiles/out","w",stdout);
    cin>>t;
    while(t--){
        init();
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            if(A[b].fs==0||A[b].fs<a) A[b]=P(a,1);
            else if(A[b].fs==a) A[b].se++;     
        }
        for(int i=0;i<m;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if(A[c].fs)
                ans[h++]=tri(A[c].fs,a,b,A[c].se);
        }
        int f=-1;
        sort(ans,ans+h);
        for(int i=0;i<h;i++){
            if(f==-1||ans[f]!=ans[i]) ans[++f]=ans[i];
            else ans[f].cnt+=ans[i].cnt;
        }
        int cnt=0;
        for(int i=0;i<=f;i++){
            int s1=B.sum(ans[i].b-1,maxv-1);
            int s2=B.sum(maxv-1,ans[i].c-1);
            int s3=B.sum(ans[i].b-1,ans[i].c-1);
            int s4=B.sum(maxv-1,maxv-1);
            if(s4-s1-s2+s3==0) cnt+=ans[i].cnt;
            B.add(ans[i].b,ans[i].c);
        }
        printf("Case #%d: %d\n",++cas,cnt);
    }
    return 0;    
}
View Code

 

posted @ 2015-11-10 19:07  PlusSeven  阅读(362)  评论(0编辑  收藏  举报