hdu5517 二维树状数组

题意是给了 n个二元组 m个三元组, 二元组可以和三元组 合并生成3元组,合并条件是<a,b> 与<c,d,e>合并成 <a,c,d> 前提是 b==e,

如果存在组合 uwv 使得u>=a w>=c v>=d 并且uwv和acd不等  就说abc 不是最优的,求问最后又多少个组合是最优的 , 这个组合中是允许重复的

我们对于每个b只取最大的a,然后让这个最大的a去和相应的b,c进行组合,然后对于这样的三元组 为了省去判断和他相等的个数,我们直接将相同的元组合并到一起去,

然后枚举a求在 在矩阵C[b][c]右下边是否存在值如果存在显然这个就不是最优的,用二维树状数组解决这个问题

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <string.h>
using namespace std;
const int maxn=100005;
struct point{
  int a,c,d,nu;
  bool operator <(const point &rhs)const{
      if(a!=rhs.a)return a<rhs.a;
      if(c!=rhs.c)return c<rhs.c;
      return d<rhs.d;
  }
  bool operator ==(const point &rhs)const{
     return a==rhs.a&&c==rhs.c&&d==rhs.d;
  }
}P[maxn];
int B[maxn];
int nu[maxn];
int C[1005][1005];
int Nc,Nd,numofC;
void init()
{
    numofC=Nc=Nd=0;
    memset(B,0,sizeof(B));
    memset(nu,0,sizeof(nu));
    memset(C,0,sizeof(C));
}
int lowbit(int x)
{
    return x&(-x);
}
void add(int c,int d,int val)
{
    for(int i=c; i<=Nc; i+=lowbit(i))
        for(int j=d; j<=Nd; j+=lowbit(j))
           C[i][j]+=val;
}
int sum(int c, int d)
{
    int ans=0;
    for(int i=c; i>0; i-=lowbit(i))
        for(int j=d; j>0; j-=lowbit(j))
          ans+=C[i][j];
    return ans;
}
int main()
{
    int cas;
    scanf("%d",&cas);
    for(int cc=1; cc<=cas; cc++)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        init();
        for(int i=0; i<n; i++)
        {
             int a,b;
             scanf("%d%d",&a,&b);
             if(B[b]<a){ B[b]=a; nu[b]=1;}
             else if(B[b]==a) nu[b]++;
        }
        for(int i=0; i<m; i++)
        {
            int c,d,e;
            scanf("%d%d%d",&c,&d,&e);
            if(nu[e]>0)
            {
                point t;
                t.a=B[e]; t.c=c; t.d=d; t.nu=nu[e];
                P[numofC++]=t;
            }
            Nc=max(c,Nc); Nd=max(Nd,d);
        }
        sort(P,P+numofC);
        int ge=1;
        for(int i=1; i<numofC; i++)
            if(P[i]==P[ge-1])P[ge-1].nu+=P[i].nu;
            else P[ge++]=P[i];
        numofC=ge;
        int ans=0;
        ge=0;
        for(int i=numofC-1; i>=0; i--)
        {
            point t=P[i];
            int s2=sum(t.c-1,Nd);
            int s3=sum(Nc,t.d-1);
            int s4=sum(t.c-1,t.d-1);
            if(ge-s2-s3+s4 == 0){
                ans+=t.nu;
            }
            ge++;
            add(t.c,t.d,1);
        }
        printf("Case #%d: %d
",cc,ans);

    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Opaser/p/4933909.html