• 算法复习——cdq分治


    题目:

    Description

    有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),又三个整数表示。现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb。显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。

    Input

    第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。
    以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性

    Output

    包含N行,分别表示评级为0...N-1的每级花的数量。

    Sample Input

    10 3
    3 3 3
    2 3 3
    2 3 1
    3 1 1
    3 1 2
    1 3 1
    1 1 2
    1 2 2
    1 3 2
    1 2 1

    Sample Output

    3
    1
    3
    0
    1
    0
    1
    0
    0
    1

    HINT

    1 <= N <= 100,000, 1 <= K <= 200,000

    Source

    题解:

      CDQ分治解三维偏序的模板题,以下是关于cdq分治的大概介绍

      

      CDQ的核心就是分为左右两组后,算左边对右边的贡献····

      但CDQ分治运用最广泛的是解决偏序的问题···比如上面的陌上花开就是解决关于(a,b,c)的三维偏序问题····

      解决这类问题的核心是降维···一个一个忽略每一维影响···比如这道题,先以a优先排序,从而只用管b和c···然后在分成左右两组时每组以b优先排序··进而最后利用树状数组解决c

      详细见:http://www.cnblogs.com/mlystdcall/p/6219421.html

      不得不说真神奇·····

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    const int M=2e5+5;
    inline int R()
    {
      char c;int f=0,i=1;
      for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
      if(c=='-')  i=-1,c=getchar();
      for(;c<='9'&&c>='0';c=getchar())
        f=(f<<3)+(f<<1)+c-'0';
      return f*i;
    }
    struct node
    {
      int x,y,z,cnt,ans;
    }f[N],a[N];
    bool cmp(node a,node b)
    {
      if(a.x==b.x&&a.y==b.y)  return a.z<b.z;
      else if(a.x==b.x)  return a.y<b.y;
      else return a.x<b.x;
    }
    int m,n,k,tot,tree[M],ans[N];
    inline bool operator < (node a,node b)
    {
      if(a.y==b.y)  return a.z<b.z;
      else return a.y<b.y;  
    }
    inline void insert(int u,int w)
    {
      for(int i=u;i<=k;i+=(i&(-i)))
        tree[i]+=w;
    }
    inline int query(int u)
    {
      int temp=0;
      for(int i=u;i>0;i-=(i&(-i)))
        temp+=tree[i];
      return temp;
    }
    inline void solve(int l,int r)
    {
      if(l==r)  return;
      int mid=(l+r)/2,i,j;
      solve(l,mid),solve(mid+1,r);
      sort(a+l,a+mid+1);sort(a+mid+1,a+r+1);
      i=l,j=mid+1;
      while(j<=r)
      {
        while(i<=mid&&a[i].y<=a[j].y)
        {
          insert(a[i].z,a[i].cnt);i++;
        }
        a[j].ans+=query(a[j].z);j++;
      }
      for(j=l;j<i;j++)  insert(a[j].z,-a[j].cnt); 
    } 
    int main()
    {
      //freopen("a.in","r",stdin);
      m=R(),k=R();
      for(int i=1;i<=m;i++)
      {
        f[i].x=R();f[i].y=R();f[i].z=R();
      }
      sort(f+1,f+m+1,cmp);
      a[++n]=f[1];tot=1;
      a[1].cnt=1;
      for(int i=2;i<=m;i++)
      {
        if(f[i].x!=f[i-1].x||f[i].y!=f[i-1].y||f[i].z!=f[i-1].z)  ++n,tot=1;
        else tot++;
        a[n]=f[i],a[n].cnt=tot;
      }
      solve(1,n);
      for(int i=1;i<=n;i++)
        ans[a[i].ans+a[i].cnt-1]+=a[i].cnt;
      for(int i=0;i<m;i++)
        printf("%d
    ",ans[i]);
      return 0;
    }
  • 相关阅读:
    多条件查询测试用例设计方法(1)—Pairwise(转)
    单例饿汉式和饱汉式各自的有缺点(转)
    Intellij IDEA生成JavaDoc(转)
    Linux常用命令分类
    Linux 常用命令
    数据库简单测试
    postman参数为Json数据结构
    WEB测试常见BUG
    APP应用测试技巧
    APP软件半成品测试技巧
  • 原文地址:https://www.cnblogs.com/AseanA/p/7519614.html
Copyright © 2020-2023  润新知