• P3810 【模板】三维偏序(陌上花开)


    题目描述

    有 nn 个元素,第 ii 个元素有 a_iaib_ibic_ici 三个属性,设 f(i)f(i) 表示满足 a_j leq a_iajai 且 b_j leq b_ibjbi 且 c_j leq c_icjci的 jj 的数量。

    对于 d in [0, n)d[0,n),求 f(i) = df(i)=d 的数量

    输入输出格式

    输入格式:

     

    第一行两个整数 nn、kk,分别表示元素数量和最大属性值。

    之后 nn 行,每行三个整数 a_iaib_ibic_ici,分别表示三个属性值。

     

    输出格式:

     

    输出 nn 行,第 d + 1d+1 行表示 f(i) = df(i)=d 的 ii 的数量。

     

    输入输出样例

    输入样例#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
    输出样例#1: 复制
    3
    1
    3
    0
    1
    0
    1
    0
    0
    1

    说明

    1 leq n leq 100000, 1 leq k leq 2000001n100000,1k200000




    就是一维排序,一维cdq,一维数据结构,

    然后就是要把萨格属性完全相同的要去掉,并在这个属性的个数上+1. 其他的就没什么了

    其实一开始看到cdq是一脸懵逼的,怎么看也看不懂,但是理解了以后就会发现这玩意也挺简单的。



     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 struct point{
     6     int a,b,c,id;
     7     point(){
     8         a=b=c=id=0;
     9     }
    10 }num[100001],tem[100001];
    11 bool cmp(point lhs,point rhs){
    12     if(lhs.a!=rhs.a)return lhs.a<rhs.a;
    13     if(lhs.b!=rhs.b)return lhs.b<rhs.b;
    14     return lhs.c<rhs.c;
    15 }
    16 int c[200001],ans[100001],fin[100001],size[100001];
    17 int n,k;
    18 void update(int ind,int num){for(;ind<=k;ind+=ind&-ind)c[ind]+=num;}
    19 long long query(int ind){
    20     long long tot=0;
    21     for(;ind;ind-=ind&-ind)tot+=c[ind];
    22     return tot;
    23 }
    24 void cdq(int l,int r){
    25     if(l==r)return;
    26     int mid=(l+r)/2;
    27     cdq(l,mid);cdq(mid+1,r);
    28     int i=l,j=mid+1,ind=l;
    29     while(i<=mid&&j<=r){
    30         if(num[i].b<=num[j].b)update(num[i].c,size[num[i].id]),tem[ind++]=num[i++];
    31         else ans[num[j].id]+=query(num[j].c),tem[ind++]=num[j++];
    32     }
    33     while(j<=r)ans[num[j].id]+=query(num[j].c),tem[ind++]=num[j++];
    34     for(int e=l;e<i;e++)update(num[e].c,-size[num[e].id]);
    35     while(i<=mid)tem[ind++]=num[i++];
    36     for(int i=l;i<=r;i++)num[i]=tem[i];
    37 }
    38 int main(){
    39     scanf("%d%d",&n,&k);
    40     for(int i=1;i<=n;i++)scanf("%d%d%d",&num[i].a,&num[i].b,&num[i].c);
    41     std::sort(num+1,num+n+1,cmp);
    42     int ind=0;
    43     for(int i=1;i<=n;i++){
    44         if(num[i].a!=num[i-1].a||num[i].b!=num[i-1].b||num[i].c!=num[i-1].c)tem[++ind]=num[i];
    45         size[ind]++;
    46     }
    47     for(int i=1;i<=ind;i++)num[i]=tem[i],num[i].id=i;
    48     cdq(1,ind);
    49     for(int i=1;i<=ind;i++)fin[ans[num[i].id]+size[num[i].id]-1]+=size[num[i].id];
    50     for(int i=0;i<n;i++)printf("%d
    ",fin[i]);
    51 }
  • 相关阅读:
    关于C++中类的static和const成员
    你搞图论有毛用啊!!
    getopt()
    算法设计与分析求最大子段和问题(蛮力法、分治法、动态规划法) C++实现
    CF183 div2 解题报告
    程序员面试中什么最重要?
    php函数基础(一)
    可变参数列表
    ThinkPHP5+小程序商城 网盘视频
    svn里update以后还是有红色的感叹号怎么办
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10425895.html
Copyright © 2020-2023  润新知