• HDU 5517---Triple(二维树状数组)


    题目链接

    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 extbf{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
     
    题意:每组数据第一行输入n m  ,第二行输入a1 b1  a2  b2......an  bn,第三行输入c1  d1  e1......cm  dm  em 
            现在定义C=A*B  即{<a,c,d>|<a,b>属于A & <c,d,e>属于B & b==e}
            然后基于C有这样一个运算TOP(C)={<a,c,d>|<a,c,d>属于C & C中不存在<u,v,w>使得 u>=a,v>=c,w>=d,<u,v,w>!=<a,c,d> }
            现在求 TOP(C)中有几个元素?
     
    思路:
              

           上面是从论坛上截图下来的,我觉得优化的时候,只需要用第一条即可,即:对于二元组(a,b) ,b相同的话只有最大的a值有效,所以对相同的b记录一下最大值的个数

           第二条不一定能优化,在极端的数据上,一点都不会优化。经过第一条的优化后,C的大小为1e5,然后用二维树状数组处理O(n)=1e5*log2(1000)*log2(1000)=1e7

           实际的数据肯定会比这个复杂度要小。

    代码如下:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=1e5+5;
    int a1[N],cnt[N];
    int c[1005][1005];
    
    struct Node
    {
        int a,c,d;
        int v;
    }tr[N];
    int cmp(const Node s1,const Node s2)
    {
        if(s1.a!=s2.a) return s1.a<s2.a;
        if(s1.c!=s2.c) return s1.c<s2.c;
        return s1.d<s2.d;
    }
    int lowbit(int x)
    {
        return x&(-x);
    }
    int query(int x)
    {
        int ans=0;
        int i=tr[x].c;
        while(i<1005)
        {
            int j=tr[x].d;
            while(j<1005)
            {
                ans+=c[i][j];
                j+=lowbit(j);
            }
            i+=lowbit(i);
        }
        return ans;
    }
    void update(int x)
    {
        int i=tr[x].c;
        while(i>0)
        {
            int j=tr[x].d;
            while(j>0)
            {
                c[i][j]++;
                j-=lowbit(j);
            }
            i-=lowbit(i);
        }
    }
    int main()
    {
        ///cout << "Hello world!" << endl;
        int t,Case=1;
        cin>>t;
        while(t--)
        {
           int n,m;
           scanf("%d%d",&n,&m);
           memset(a1,-1,sizeof(a1));
           memset(c,0,sizeof(c));
           for(int i=1;i<=n;i++)
          {
              int a,b;
              scanf("%d%d",&a,&b);
              if(a1[b]<a){
                 a1[b]=a;
                 cnt[b]=1;
              }
              else if(a1[b]==a) cnt[b]++;
          }
          int num=0;
          for(int i=1;i<=m;i++)
          {
              int c,d,e;
              scanf("%d%d%d",&c,&d,&e);
              if(a1[e]==-1) continue;
              tr[num].a=a1[e];
              tr[num].c=c;
              tr[num].d=d;
              tr[num++].v=cnt[e];
          }
          sort(tr,tr+num,cmp);
          int flag=0;
          int k=0;
          for(int i=1;i<num;i++)
          {
              if(tr[i].a==tr[k].a&&tr[i].c==tr[k].c&&tr[i].d==tr[k].d)
              {
                  tr[k].v+=tr[i].v;
              }
              else{
                 k++;
                 flag=1;
                 tr[k].a=tr[i].a;
                 tr[k].c=tr[i].c;
                 tr[k].d=tr[i].d;
                 tr[k].v=tr[i].v;
              }
          }
          long long ans=0;
          if(flag)  ///防止 1 1 (1,1) (1,1,2) 这样的数据(但是HDU上没这样的数据);
          for(int i=k;i>=0;i--)
          {
              if(!query(i)) ans+=(long long)tr[i].v;
              update(i);
          }
          printf("Case #%d: %lld
    ",Case++,ans);
        }
        return 0;
    }
  • 相关阅读:
    Java集合一
    集合类视图
    NIO
    IO补充
    线程图
    线程池
    Callable
    element-ui upload组件上传图片时限制图片宽高
    vue-router 使用a链接跳转至二级子页面偶尔会出现地址栏看不见路由和参数的情况
    vue中引入jquery报错问题
  • 原文地址:https://www.cnblogs.com/chen9510/p/6995583.html
Copyright © 2020-2023  润新知