• BZOJ3262: 陌上花开(三维偏序,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

    解题思路:

    CDQ分治很好的模板。

    运用了线段树/树状数组扫描线的思想。

    或者说是离线解题时的控制端点动态更新。

    动态处理问题获得解还是非常神的思路。

    相当于将解集拆分成若干份,每份使用动态统计。

    换句话说,就是将一定范围内的数据配对时间复杂度降低。

    注意要撤销操作。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 struct pnt{
      6     int x,y,z,f,w;
      7     bool friend operator == (pnt a,pnt b)
      8     {
      9         return a.x==b.x&&a.y==b.y&&a.z==b.z;
     10     }
     11     bool friend operator != (pnt a,pnt b)
     12     {
     13         return !(a.x==b.x&&a.y==b.y&&a.z==b.z);
     14     }
     15 }p[1000001],q[1000001];
     16 int n,k;
     17 int cnt;
     18 int d[1000001];
     19 int line[1000001];
     20 int has[1000001];
     21 int lowbit(int x)
     22 {
     23     return x&(-x);
     24 }
     25 bool cmx(pnt a,pnt b)
     26 {
     27     if(a.x==b.x&&a.y==b.y)
     28         return a.z<b.z;
     29     if(a.x==b.x)
     30         return a.y<b.y;
     31     return a.x<b.x;
     32 }
     33 bool cmy(pnt a,pnt b)
     34 {
     35     if(a.x==b.x&&a.y==b.y)
     36         return a.z<b.z;
     37     if(a.y==b.y)
     38         return a.x<b.x;
     39     return a.y<b.y;
     40 }
     41 void add(int p,int v)
     42 {
     43     while(p<=k)
     44     {
     45         line[p]+=v;
     46         p+=lowbit(p);
     47     }
     48     return ;
     49 }
     50 int ask(int p)
     51 {
     52     int ans=0;
     53     while(p)
     54     {
     55         ans+=line[p];
     56         p-=lowbit(p);
     57     }
     58     return ans;
     59 }
     60 void wrk(int l,int r)
     61 {
     62     int m=(l+r)>>1;
     63     sort(p+l,p+m+1,cmy);
     64     sort(p+m+1,p+r+1,cmy);
     65     int tmp=-1;
     66     for(int i=l,j=m+1;j<=r;j++)
     67     {
     68         for(;i<=m&&p[i].y<=p[j].y;i++)
     69         {
     70             add(p[i].z,p[i].w);
     71             tmp=i;
     72         }
     73         p[j].f+=ask(p[j].z);
     74     }
     75     for(int i=l;i<=tmp;i++)
     76         add(p[i].z,-p[i].w);
     77 }
     78 void cdq(int l,int r)
     79 {
     80     if(l==r)
     81         return ;
     82     int m=(l+r)>>1;
     83     cdq(l,m);
     84     cdq(m+1,r);
     85     wrk(l,r);
     86 }
     87 int main()
     88 {
     89     scanf("%d%d",&n,&k);
     90     for(int i=1;i<=n;i++)
     91         scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
     92     sort(q+1,q+n+1,cmx);
     93     int wgt=0;
     94     for(int i=1;i<=n;i++)
     95     {
     96         wgt++;
     97         if(q[i]!=q[i+1])
     98         {
     99             p[++cnt]=q[i];
    100             p[cnt].w=wgt;
    101             wgt=0;
    102         }
    103     }
    104     swap(cnt,n);
    105     cdq(1,n);
    106     for(int i=1;i<=n;i++)
    107         has[p[i].f+p[i].w-1]+=p[i].w;
    108     for(int i=0;i<cnt;i++)
    109         printf("%d
    ",has[i]);
    110     return 0;
    111 }
  • 相关阅读:
    改进初学者的PID-微分冲击
    孤独
    改进初学者的PID-采样时间
    mac10.9下eclipse的storm开发环境搭建
    ubuntu12.04+hadoop2.2.0+zookeeper3.4.5+hbase0.96.2+hive0.13.1伪分布式环境部署
    Linux学习笔记之rpm包管理功能全解
    Linux学习笔记之文件读取过程
    Linux学习笔记之Linux系统的swap分区
    Linux学习笔记之grep命令和使用正则表达式
    Prometheus监控学习笔记之容器监控Grafana模块
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10115702.html
Copyright © 2020-2023  润新知