• 陌上花开(三维偏序)


    其实还是比较好理解的qaq。。。

    先来看题:

    题目描述

    有 n 个元素,第 i 个元素有 aibici 三个属性,设 f(i) 表示满足 ajai 且bjbi 且cjci 的 j 的数量。

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

    输入输出格式

    输入格式: 

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

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

    输出格式:

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

    输入输出样例

    输入样例#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的一道板子题,我们先来明确一下到底什么是CDQ?

    CDQ通俗一点说就是三句话:

    1.递归前一半

    2.判断前一半对于后一半的影响

    3.递归后一半

    那么我们来看这道经典的三维偏序题,说一下大体的思路:

    首先我们可以以x作为第一关键字进行排序,(y和z作为次要关键字),这样我们就可以保证从左到右是以x单调递增的。

    然后我们将这个区间一分为二,分别对于每一个序列以y作为第一关键字排序,这样一来我们得到的两个序列拥有以下的性质:

    1.左序列的任意x值都小于右序列的任意x值

    2.每一个序列里的y值都是单调递增的

    最后我们分别在序列头和序列中点设定两个指针j和i,对于每一个i,j都从头开始枚举,将j对应的y小于i对应的y的j加入树状数组中,最后只要判断z值是否满足条件就可以了。

    当然,这道题还有一些小细节:

    1.由于原序列可能会有重复的数,我们要先进行去重,并储存每一个数都代表了几个相同的数。

    2.每一次i的增加都要清空树状数组,只要加上之前加的相反数就可以了。

    好像也就这些了。。。

    最后,附上本题代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 #define maxn 100010
      4 #define maxk 200010
      5 using namespace std;
      6 struct node
      7 {
      8     int x,y,z,ans,w;
      9 };
     10 node a[maxn],b[maxn];
     11 int n,cnt[maxk];
     12 int k,z;
     13 bool cmp1(node u,node v)
     14 {
     15     if(u.x==v.x)
     16     {
     17         if(u.y==v.y)
     18             return u.z<v.z;
     19         return u.y<v.y;
     20     }
     21     return u.x<v.x;
     22 }
     23 bool cmp2(node u,node v)
     24 {
     25     if(u.y==v.y)
     26         return u.z<v.z;
     27     return u.y<v.y;
     28 }
     29 struct TREE
     30 {
     31     int tre[maxk],kk;
     32     int lowbit(int x)
     33     {
     34         return x&(-x);
     35     }
     36     int ask(int i)
     37     {
     38         int ans=0;
     39         for(; i; i-=lowbit(i))
     40         {
     41             ans+=tre[i];
     42         }
     43         return ans;
     44     }
     45     void add(int i,int k)
     46     {
     47         for(; i<=kk; i+=lowbit(i))
     48         {
     49             tre[i]+=k;
     50         }
     51     }
     52 } t;
     53 void cdq(int l,int r)
     54 {
     55     if(l==r)
     56     {
     57         return;
     58     }
     59     int mid=(l+r)>>1;
     60     cdq(l,mid);
     61     cdq(mid+1,r);
     62     sort(a+l,a+mid+1,cmp2);
     63     sort(a+mid+1,a+r+1,cmp2);//可能大家会有一些疑问,但是这个就是指针的用法,上面的是从l到mid,下面是mid+1到r
     64     int i=mid+1,j=l;
     65     while(i<=r)
     66     {
     67         while(a[j].y<=a[i].y && j<=mid)
     68         {
     69             t.add(a[j].z,a[j].w);
     70             j++;
     71         }
     72         a[i].ans+=t.ask(a[i].z);
     73         i++;
     74     }
     75     for(i=l; i<j; i++)
     76     {
     77         t.add(a[i].z,-a[i].w);
     78     }
     79 }
     80 int main()
     81 {
     82     scanf("%d%d",&z,&k);//z是数量,k是最大属性值
     83     t.kk=k;//设定上限,t是维护的树状数组
     84     for(int i=1; i<=z; i++)
     85     {
     86         scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].z);//
     87     }
     88     sort(b+1,b+z+1,cmp1);//排序
     89     int c=0;
     90     for(int i=1; i<=z; i++)
     91     {
     92         c++;
     93         if(b[i].x!=b[i+1].x || b[i].y!=b[i+1].y || b[i].z!=b[i+1].z )
     94             a[++n]=b[i],a[n].w=c,c=0;
     95     }//去重
     96     cdq(1,n);//cdqaq
     97     for(int i=1; i<=n; i++)
     98     {
     99         cnt[a[i].ans+a[i].w-1]+=a[i].w;//这个地方不太好理解:cnt【x】就是储存f【i】= x的个数,x就等于i的答案加上它重复的个数(可以取等)减去本身
    100 } 101 for(int i=0; i<z; i++) 102 { 103 printf("%d ",cnt[i]); 104 } 105 return 0; 106 }
  • 相关阅读:
    漂亮的表格样式;jQuery清楚表格所有行;js解析后台传过来的JSON数据;动态生成表格数据
    js下载文件;下载方式<a> 和href方式;已经中文乱码问题
    oracle数据库优化与LNNVL函数使用
    HTML页面中使用JQuery获取表格的所有单元的的数据
    oracle中 SQL语句查询后;拼接列;拼接行
    页面制作验证码
    jqGrid,样式
    html 页面弹窗
    Java float保留两位小数或多位小数
    VB操作EXCEL文件大全
  • 原文地址:https://www.cnblogs.com/yufenglin/p/10395461.html
Copyright © 2020-2023  润新知