hdu 5517 Triple 二维树状数组

来源:互联网 发布:乐天破产知乎 编辑:程序博客网 时间:2024/06/11 01:33


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
25 91 1 2 2 3 3 3 3 4 21 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 33 42 7 2 7 2 71 4 7 2 3 7 3 2 7 4 1 7
 

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

Source
2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)
 

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


0 0
原创粉丝点击