【模板】三维偏序

CDQ分治

首先按a排序,分成两段后再分别对两段按b排序,这样就保证了w[x2].a>=w[x1].a,消去一维

按b排序后找到w[x2].b>=w[x1].b的同时满足w[x2].c>=w[x1].c的值

按b排序后有单调性,所以b可以在O(n)时间,对于c,每找到一个w[x1]满足b的条件,则在树状数组中+1

w[x2].ans+=query(w[x2].c)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 struct Node
 7 {
 8     int a,b,c,cnt,ans;
 9 }w[100001];
10 int m,n,c[2000001],ans,f[100001];
11 bool cmp2(Node a,Node b)
12 {
13     if (a.b==b.b)
14      return a.c<b.c;
15      else return a.b<b.b;
16 }
17 bool cmp1(Node a,Node b)
18 {
19     if (a.a==b.a)
20      return cmp2(a,b);
21      else return a.a<b.a;
22 }
23 void add(int x,int d)
24 {
25     while (x<=m)
26     {
27      c[x]+=d;
28      x+=(x&(-x));
29     }
30 }
31 int query(int x)
32 {int s=0;
33     while (x)
34     {
35      s+=c[x];
36      x-=(x&(-x));
37     }
38   return s;
39 }
40 void cdq(int l,int r)
41 {int r1,r2;
42     int mid=(l+r)/2;
43     if (l==r)
44     return;
45      cdq(l,mid);cdq(mid+1,r);
46      sort(w+l,w+mid+1,cmp2);
47      sort(w+mid+1,w+r+1,cmp2);
48      r1=l;r2=mid+1;
49      while (r2<=r)
50      {
51         while (r1<=mid&&w[r1].b<=w[r2].b)
52          add(w[r1].c,w[r1].cnt),r1++;
53          w[r2].ans+=query(w[r2].c);
54         r2++;
55      }
56     for (int i=l;i<=r1-1;i++)
57     add(w[i].c,-w[i].cnt);
58 }
59 int main()
60 {int i,j,num=0;
61     cin>>n>>m;
62     for (i=1;i<=n;i++)
63     {
64       scanf("%d%d%d",&w[i].a,&w[i].b,&w[i].c);
65       w[i].cnt=1;
66     }
67     sort(w+1,w+n+1,cmp1);
68     for (i=1;i<=n;i++)
69     {
70         int k=i+1;
71         while (w[i].a==w[k].a&&w[i].b==w[k].b&&w[i].c==w[k].c)
72          k++;
73          num++;
74          k--;
75          w[i].cnt+=k-i;
76          w[num]=w[i];
77          i=k;
78     }
79     cdq(1,num);
80     for (i=1;i<=num;i++)
81     f[w[i].ans+w[i].cnt-1]+=w[i].cnt;
82     for (i=0;i<n;i++)
83     printf("%d\n",f[i]);
84 }
时间: 2024-12-26 16:44:15

【模板】三维偏序的相关文章

[模板] 三维偏序 - 树套树,线段树

#include <bits/stdc++.h> using namespace std; const int N = 2e+7 + 5; struct Pt { int a, b, c; int id; bool operator<(const Pt &x) const { return a < x.a; } } p[N]; map<int, int> ma, mb, mc; int aa[N], ab[N], ac[N]; int ida, idb, idc

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

题目背景 这是一道模板题 可以使用bitset,CDQ分治,K-DTree等方式解决. 题目描述 有 nn 个元素,第 ii 个元素有 a_iai?.b_ibi?.c_ici? 三个属性,设 f(i)f(i) 表示满足 a_j \leq a_iaj?≤ai? 且 b_j \leq b_ibj?≤bi? 且 c_j \leq c_icj?≤ci? 的 jj 的数量. 对于 d \in [0, n)d∈[0,n),求 f(i) = df(i)=d 的数量 输入输出格式 输入格式: 第一行两个整数 n

HDU 5618:Jam&#39;s problem again(CDQ分治+树状数组处理三维偏序)

http://acm.hdu.edu.cn/showproblem.php?pid=5618 题意:-- 思路:和NEUOJ那题一样的.重新写了遍理解了一下,算作处理三维偏序的模板了. 1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 #d

P3810 -三维偏序(陌上花开)cdq-分治

P3810 [模板]三维偏序(陌上花开) 思路 :按照 1维排序 二维 分治三维树状数组维护 #include<bits/stdc++.h> using namespace std; #define maxn 234567 int n,k,id,s,tree[maxn*2],tong[maxn]; struct node { int a,b,c,ans,w; node() { ans=0; w=0; } } data[maxn]; bool cp1(node x,node y) { if(x.

BZOJ 3262: 陌上花开 [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行,每

SPOJ LIS2 Another Longest Increasing Subsequence Problem 三维偏序最长链 CDQ分治

Another Longest Increasing Subsequence Problem Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=19929 Description Given a sequence of N pairs of integers, find the length of the longest incre

P2433 - 【BZOJ 3262三维偏序】陌上花开------三维偏序

P2433 - [BZOJ 3262三维偏序]陌上花开 Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量. 定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb.显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,

NEUOJ 1702 撩妹全靠魅力值 (三维偏序)

题目链接:http://acm.neu.edu.cn/hustoj/problem.php?id=1702 题目大意:就是问每个人三个属性同时不低于另外几个人....人不分先后 经典的三维偏序问题 解题思路:CDQ分治练手题 1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using nam

【三维偏序】【分块】bzoj3262 陌上花开

裸的三维偏序. 对x坐标排序,y.z坐标分块.复杂度O(n*sqrt(n*log(n))).代码很短. 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 struct Point{int x,y,z,num;void Read(){scanf("%d%d%d",&x,&

BZOJ 3295:[Cqoi2011]动态逆序对(三维偏序 CDQ分治+树状数组)

http://www.lydsy.com/JudgeOnline/problem.php?id=3295 题意:简单明了. 思路:终于好像有点明白CDQ分治处理三维偏序了.把删除操作看作是插入操作,那么可以按照插入的时间顺序看作是一维x,插入的数在原本序列的下标是一维y,插入的数本身是一维z.那么问题可以转化成每插入一个数(xx,yy,zz),求有多少个数(x,y,z)使得 x < xx,y < yy,z > zz .一开始先对 x 进行排序,然后进行CDQ分治.这样可以干掉一维,保证随