• [BZOJ3262]陌上花开


    陌上花开

    题目描述

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

    输入格式

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

    输出格式

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

    样例

    样例输入

    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
    

    样例输出

    3
    1
    3
    0
    1
    0
    1
    0
    0
    1

    膜拜CDQ小姐姐

    CDQ分治一般情况下会用来解决三维偏序问题,一般的套路是第一维直接快排,然后进行CDQ分治,在分治过程中通过归并再次使得第二维有序,当然,不归并可以再次对部分数据快排,打起来肯定快排爽,不过过程中要处理的东西处理起来应该也有点难受,如果代码能力是大佬,就当刚才什么都没说,由于进行操作前已经保证了第一维有序,左区间均可对右区间作出贡献,所以在归并第二维时第一维已经不重要了,第三维的有序一般通过树状数组等数据结构实现,需要注意的是对于维护第三维的数据结构需要每次清空,但是千万不要memset之类的全部清空,别觉得memset一句话就快,他就是O(n),只需要清空当前区间,不然很可能T到飞起,上述就是CDQ分治的基本思路

    陌上花开是CDQ最经典的三维偏序问题,思路就是上述那个,这题需要注意的是由于等于的存在,要在排序之后去重,其他的,树状数组记得打对,存的是第三维,记得不管是数组范围还是操作结尾,均是k而不是n,来自WA了6遍的调了一天半的过来人的提醒,图就不贴了,丢人

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define maxn 100100
     5 using namespace std;
     6 struct node{
     7     int s,c,m,sum,js;
     8 }a[maxn],gb[maxn];
     9 int n,k,tot;
    10 int c[maxn*2],ans[maxn];
    11 bool cmp(const node &a,const node &b)
    12 {
    13     if(a.s!=b.s)  return a.s<b.s;
    14     if(a.c!=b.c)  return a.c<b.c;
    15     return a.m<b.m;
    16 }
    17 int lowbit(int x)
    18 {
    19     return x&(-x);
    20 }
    21 void add(int x,int w)
    22 {
    23     for(int i=x;i<=k;i+=lowbit(i))  c[i]+=w;
    24 }
    25 int getsum(int w)
    26 {
    27     int ans=0;
    28     for(int i=w;i;i-=lowbit(i))  ans+=c[i];
    29     return ans;
    30 }
    31 void cdq(int l,int r)
    32 {
    33     if(l==r)  return ;
    34     int mid=(l+r)>>1,ll=l,rr=mid+1,zz=l;
    35     cdq(l,mid);  cdq(mid+1,r);
    36     while(ll<=mid&&rr<=r)
    37     {
    38         if(a[ll].c<=a[rr].c)  {add(a[ll].m,a[ll].js);  gb[zz++]=a[ll++];}
    39         else  {a[rr].sum+=getsum(a[rr].m);  gb[zz++]=a[rr++];}
    40     }
    41     while(ll<=mid)  {add(a[ll].m,a[ll].js);  gb[zz++]=a[ll++];}
    42     while(rr<=r)  {a[rr].sum+=getsum(a[rr].m);  gb[zz++]=a[rr++];}
    43     for(int i=l;i<=r;++i)
    44     {
    45         if(i<=mid)  add(a[i].m,-a[i].js);
    46         a[i]=gb[i];
    47     }
    48 }
    49 int main()
    50 {
    51     scanf("%d%d",&n,&k);
    52     for(int i=1;i<=n;++i)  scanf("%d%d%d",&a[i].s,&a[i].c,&a[i].m);
    53     sort(a+1,a+n+1,cmp);
    54     for(int i=1;i<=n;++i)
    55     {
    56         if(a[i].s==a[tot].s&&a[i].c==a[tot].c&&a[i].m==a[tot].m)  a[tot].js++;
    57         else  {a[++tot].s=a[i].s;  a[tot].c=a[i].c;  a[tot].m=a[i].m;  a[tot].js=1;}
    58     }
    59     cdq(1,tot);
    60     for(int i=1;i<=tot;++i)  ans[a[i].sum+a[i].js-1]+=a[i].js;
    61     for(int i=0;i<n;++i)  printf("%d
    ",ans[i]);
    62     return 0;
    63 }
    一定写对树状数组
  • 相关阅读:
    【Java】Swing-LookAndFeel 初解
    【软件】软件发布版本号说明
    【Gradle】Gradle compile 运用
    【Java】String,StringBuilder,StringBuffer 区别与实现
    Java面试题
    java面向对象_抽象类和接口
    Java学习_int和Integer的区别+包装类
    PHP-格式标签
    PHP+Zend 输出时中文乱码问题
    JSP学习
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11269247.html
Copyright © 2020-2023  润新知