Triple HDU - 5517 二维树状数组

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

C=AB={a,c,da,bA, c,d,eB and b=e} C=A∗B={⟨a,c,d⟩∣⟨a,b⟩∈A, ⟨c,d,e⟩∈B and b=e} 

For each  a,b,cC ⟨a,b,c⟩∈C, its BETTER set is defined as 

BETTERC(a,b,c)={u,v,wCu,v,wa,b,c, ua, vb, wc} BETTERC(⟨a,b,c⟩)={⟨u,v,w⟩∈C∣⟨u,v,w⟩≠⟨a,b,c⟩, u≥a, v≥b, w≥c} 

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

TOP(C)={a,b,cCBETTERC(a,b,c)=} TOP(C)={⟨a,b,c⟩∈C∣BETTERC(⟨a,b,c⟩)=∅} 

You need to compute the size of  TOP(C) TOP(C).
Input
The input contains several test cases. The first line of the input is a single integer  t (1t10) t (1≤t≤10) which is the number of test case. Then  t t test cases follow. 

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

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

corresponding to the  m m triples of integers in  B B, where  1ci,di103 1≤ci,di≤103 and  1ei105 1≤ei≤105.
Output
For each test case, you should output the size of set  TOP(C) 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
 
  
题意是给你n个二元组a,b  m个三元组c,d,e,让你找B==e的组成集合c(a,c,d)问这个集合中 a,c,d不全部大于等于其他的有几个。
要是就按b==e的全加进去,然后在二重循环比较肯定要超时的。
所以我们可以先处理a,b  b相等时就选大的a,因为小的a最后肯定要被去掉的。
然后我们就按是否be相等建好集合。按a排序从小到大,从后往前找。
这样后面的a肯定大于前面的a 要是后面的c,d也大于等于前面的,那就肯定不符合了。所以就想到了二维树状数组。
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100005;
int a[100005];
int num[100005];
int c[1005][1005];
struct node
{
    int a,c,d;
    int num;
}y[maxn];
int cmp(node q,node w)
{
    if(q.a!=w.a)return q.a<w.a;
    else if(q.c!=w.c)return q.c<w.c;
    else return q.d<w.d;
}
int lowbit(int i)
{
    return i&(-i);
}
int query(int x)
{
     int sum=0;
     int i=y[x].c;
     while(i<1004)
     {
         int j=y[x].d;
         while(j<1004)
         {
             sum+=c[i][j];
             j+=lowbit(j);
             //cout<<i<<" "<<j<<endl;
         }

         i+=lowbit(i);
     }
     return sum;
}
void update(int x)
{
    int i=y[x].c;
    while(i>0)
    {
        int j=y[x].d;
        while(j>0)
        {
            c[i][j]++;
            j-=lowbit(j);
        }
        i-=lowbit(i);
    }
}
int main()
{
    int t;
    cin>>t;
    int cc=1;
    while(t--)
    {
        int n,m;
        memset(c,0,sizeof(c));
        memset(a,-1,sizeof(a));
        //memset(num,0,sizeof(num));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            int a1,b;
            scanf("%d%d",&a1,&b);
            if(a[b]<a1)
            {
                a[b]=a1;                       //对于每个b记录最大的a1
                num[b]=1;                                    //更新他所对应的数量值
            }
            else if(a[b]==a1)
            {
                num[b]++;
            }
        }
        int z=1;
        for(int i=1;i<=m;i++)
        {
            int c,d,e;
            scanf("%d%d%d",&c,&d,&e);
            if(a[e]==-1)continue;

                y[z].a=a[e];
                y[z].c=c;
                y[z].d=d;
                y[z++].num=num[e];                            //继承之前就重复的元素

        }
        sort(y+1,y+z,cmp);                                            //按三个值从小到大的顺序排序
        int xx=z-1;
        z=1;
        int flag=0;
        y[z].a=y[z].a;
        y[z].c=y[z].c;
        y[z].d=y[z].d;
        y[z].num=y[z].num;
        for(int i=2;i<=xx;i++)
        {
            if(y[z].a==y[i].a&&y[z].d==y[i].d&&y[z].c==y[i].c)
                y[z].num+=y[i].num;
            else
            {
               flag=1;
                y[++z].a=y[i].a;
                y[z].c=y[i].c;
                y[z].d=y[i].d;
                y[z].num=y[i].num;
            }
        }
        long long  ans=0;
        //out<<"kovkdfv"<<endl;
        if(flag)
        for(int i=z;i>=1;i--)
        {
            if(!query(i))ans+=(long long) y[i].num;
            update(i);
        }
        printf("Case #%d: %d\n",cc++,ans);

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mayuqing98/article/details/79112710