hdu 5517 Triple 二维树状数组


Triple

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 571    Accepted Submission(s): 204


Problem Description
Given the finite  multi-set  A  of  n  pairs of integers, an another finite  multi-set  B  of  m  triples of integers, we define the product of  A  and  B  as a  multi-set

C=AB={a,c,da,bA, c,d,eB and b=e}

For each  a,b,cC , its BETTER set is defined as

BETTERC(a,b,c)={u,v,wCu,v,wa,b,c, ua, vb, wc}

As a \textbf{multi-set} of triples, we define the TOP subset (as a multi-set as well) of  C , denoted by  TOP(C) , as

TOP(C)={a,b,cCBETTERC(a,b,c)=}

You need to compute the size of  TOP(C) .
 

Input
The input contains several test cases. The first line of the input is a single integer  t (1t10)  which is the number of test case. Then  t  test cases follow.

Each test case contains three lines. The first line contains two integers  n (1n105)  and  m (1m105)  corresponding to the size of  A  and  B  respectively.
The second line contains  2×n  nonnegative integers
a1,b1,a2,b2,,an,bn

which describe the multi-set  A , where  1ai,bi105 .
The third line contains  3×m  nonnegative integers
c1,d1,e1,c2,d2,e3,,cm,dm,em

corresponding to the  m  triples of integers in  B , where  1ci,di103  and  1ei105 .
 

Output
For each test case, you should output the size of set  TOP(C) .
 

Sample Input
  
  
2 5 9 1 1 2 2 3 3 3 3 4 2 1 4 1 2 2 1 4 1 1 1 3 2 3 2 2 4 1 2 2 4 3 3 2 3 4 1 3 3 4 2 7 2 7 2 7 1 4 7 2 3 7 3 2 7 4 1 7
 

Sample Output
  
  
Case #1: 5 Case #2: 12
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5932  5931  5930  5929  5928 
 

Statistic |  Submit |  Discuss |  Note


题意: 
给出n个二元组<a,b>和m个三元组<c,d,e>现在将其组合成一个新的三元组集合,新三元组中允许有重复元素,一个二元组和一个三元组可以组合当且仅当b==e时将其组合成<a,c,d>,在新组合的三元组中任取一元素<a,b,c>,如果在新组合存在一个元素<u,v,w>使得u!=a && v!=b && w!=c 同时 u>=a && v>=b &&w>=c 则元素<a,b,c>不统计在答案的集合中,否则统计在答案的集合中,问最终答案的集合中有多少元素,可以有重复元素。 

要点:

1.如果b相同,取最大的a这个只需要用数组实现即可

2.对于相同的元素定义一个权值表示数量

3.由于b只有和e相同时才能构成新元素,所以集合里最多有1e5个元素,因为每一个e最多对应一个b,一个b对应一个a。

4.二维树状数组处理的是一个矩阵,插入元素时,按a从大到小,在此基础上按c再按d从大到小排序(或先d后c)



#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;

#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s)  memset(a,x,(s)*sizeof a[0])
#define mem(a,x)  memset(a,x,sizeof a)
#define ysk(x)  (1<<(x))
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxN= 1e5+0.5   ;
int N,M;
int num[maxN+5],maxa[maxN+5];
int n2,kase=0;


struct Point
{
    int a,c,d,w;
    Point(){}
    Point(int a,int c,int d,int w):a(a),c(c),d(d),w(w){}
    bool operator<(const Point i)const
    {
        if(a!=i.a)  return a<i.a;
        if(c!=i.c)  return c<i.c;
        return d<i.d;

    }
    bool operator==(const Point i)const
    {
        return a==i.a&&c==i.c&&d==i.d;
    }
}p[maxN+10];

struct BitTree
{
    int n,C[1003][1003];
    void init()
    {
       mem(C,0);
       n=1000;
    }

    void update(int x,int y)
    {
        for(int i=x;i<=n;i+=i&(-i))
        {
             for(int j=y;j<=n;j+=j&(-j) )
             {
                 C[i][j]++;
             }
        }
    }

    int query(int x,int y)
    {
        int ans=0;
        for(int i=x;i;i-=i&(-i))
        {
            for(int j=y;j;j-=j&(-j))
            {
                ans+=C[i][j];
            }
        }
        return ans;
    }
    int cal(int x,int y)
    {
        return query(1000,1000)-query(1000,y-1)-query(x-1,1000)+query(x-1,y-1);
    }

}bt;
void init()
{
    int a,b,c,d;
    mem(maxa,0);
    mem(num,0);

    for0(i,N)
    {
        cin>>a>>b;
        if(a>maxa[b])
        {
            maxa[b]=a;
            num[b]=1;
        }
        else if(a==maxa[b])
        {
             num[b]++;
        }
    }

    n2=0;
    for0(i,M)
    {
        cin>>c>>d>>b;
        if(!num[b])  continue;
        p[n2++]=Point(maxa[b],c,d,num[b]);
    }
    sort(p,p+n2);

    int n3=0;
    for(int i=1;i<n2;i++)
    {
        if(p[i]==p[n3]) p[n3].w+=p[i].w;
        else p[++n3]=p[i];
    }
    n2=n3;
}

void solve()
{
    bt.init();
    ll ans=0;
    for(int i=n2;i>=0;i--)
    {
        if(!bt.cal(p[i].c,p[i].d )) ans+=p[i].w;

        bt.update(p[i].c,p[i].d);
    }
    printf("Case #%d: %lld\n",++kase,ans);
}
int main()
{
   std::ios::sync_with_stdio(false);kase=0;
   int T;cin>>T;
   while(T--)
   {
       cin>>N>>M;
       init();
       solve();
   }
   return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值