Hdu5517 Triple

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=A∗B=\lbrace \langle a,c,d \rangle \mid \langle a,b \rangle \in A, \langle c,d,e \rangle \in B \; and \; b=e \rbrace\]
For each ⟨a,b,c⟩∈C, its BETTER set is defined as
\[BETTER_{C}(\langle a,b,c \rangle )=\lbrace \langle u,v,w \rangle \in C \mid \langle u,v,w \rangle \neq \langle a,b,c \rangle, u \ge a, v \ge b, w \ge c \rbrace\]
As a multi-set of triples, we define the TOP subset (as a multi-set as well) of \(C\), denoted by \(TOP(C)\), as
\[TOP(C)=\lbrace \langle a,b,c \rangle \in C \mid BETTER_{C}(\langle a,b,c \rangle \rbrace ) = \phi\]
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 (1 \le t \le 10)\) 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 (1 \le n \le 10^{5})\) and \(m (1 \le m \le 10^{5})\) corresponding to the size of \(A\) and \(B\) respectively.
The second line contains \(2 \times n\) nonnegative integers \(a_{1},b_{1},a_{2},b_{2},\cdots,a_{n},b_{n}\) which describe the multi-set \(A\), where \(1 \le a_{i},b_{i} \le 10^{5}\).
The third line contains \(3 \times m\) nonnegative integers \(c_{1},d_{1},e_{1},c_{2},d_{2},e_{3},\cdots,c_{m},d_{m},e_{m}\) corresponding to the \(m\) triples of integers in \(B\), where \(1 \le c_{i},d_{i} \le 10^{3}\) and \(1 \le e_{i} \le 10^{5}\).

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

首先对于二元组\(\langle a_{1},b \rangle,\langle a_{2},b \rangle \dots\)我肯定直选\(a\)最大的与\(B\)集合中的元素配对。不妨设最大的为\(a_{1}\),若我选择了\(a_{i}\)配对,那么\[\langle a_{1},c,d \rangle \in BETTER_{C}\langle a_{i},b,c \rangle\]
所以\(C\)中有用的元素减少到了\(O(N)\)个。之后就是要找的极大的三元组的个数,这个CDQ分治或者二维树状数组都行(就是最大非升子序列长度为\(1\)的元素个数)。

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

typedef long long ll;
#define lowbit(a) (a&(-a))
#define maxm (1010)
#define maxn (100010)
int T,tot,cnt,N,M,A[maxn],nA[maxn],tree[maxm][maxm]; ll ans;
struct node { int a,b; }; vector <node> B[maxn];
struct mode
{
    int a,b,c; ll num;
    friend inline bool operator <(const mode &x,const mode &y)
    {
        if (x.a != y.a) return x.a < y.a;
        else
        {
            if (x.b != y.b) return x.b < y.b;
            else return x.c < y.c;
        }
    }
    friend inline bool operator ==(const mode &x,const mode &y) { return x.a == y.a&&x.b == y.b&&x.c == y.c; }
}C[maxn],bac[maxn]; 

inline bool cmp(int x,int y) { return x > y; }

inline void ins(int i,int y)
{
    for (;i <= 1000;i += lowbit(i))
        for (int j = y;j <= 1000;j += lowbit(j)) ++tree[i][j];
}
inline int calc(int i,int y)
{
    int ret = 0;
    for (;i;i -= lowbit(i)) for (int j = y;j;j -= lowbit(j)) ret += tree[i][j];
    return ret;
}

inline void init()
{
    tot = cnt = ans = 0; memset(tree,0,sizeof(tree));
    for (int i = 1;i <= 100000;++i) A[i] = nA[i] = 0,B[i].clear();
}

int main()
{
    freopen("5517.in","r",stdin);
    freopen("5517.out","w",stdout);
    scanf("%d",&T);
    for (int Cas = 1;Cas <= T;++Cas)
    {
        printf("Case #%d: ",Cas);
        scanf("%d %d",&N,&M); init();
        for (int i = 1;i <= N;++i)
        {
            int a,b; scanf("%d %d",&a,&b);
            if (a > A[b]) A[b] = a,nA[b] = 1;
            else if (a == A[b]) nA[b]++;
        }
        for (int i = 1;i <= M;++i)
        {
            int a,b,c; scanf("%d %d %d",&a,&b,&c);
            B[c].push_back((node){a,b});
        }
        for (int i = 1;i <= 100000;++i)
            if (A[i]&&!B[i].empty())
                for (int j = 0,nn = B[i].size();j < nn;++j)
                    bac[++tot] = (mode){A[i],B[i][j].a,B[i][j].b,nA[i]};
        sort(bac+1,bac+tot+1);
        for (int i = 1,j;i <= tot;i = j)
        {
            for (j = i+1;j <= tot&&bac[j] == bac[i];++j) bac[i].num += bac[j].num;
            C[++cnt] = bac[i];
        }
        for (int i = cnt;i;--i)
        {
            int p1 = 1000-C[i].b+1,p2 = 1000-C[i].c+1;
            if (!calc(p1,p2)) ans += C[i].num; ins(p1,p2);
        }
        cout << ans << endl;
    }
    fclose(stdin); fclose(stdout);
    return 0;
}

转载于:https://www.cnblogs.com/mmlz/p/5961350.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值