HDU4742 CDQ分治,三维LIS

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4742

题意:

每个球都有三个属性值x,y,z,要求最长的lis的长度和方案数

题解:

一维LIS很好求,dp一下就行

二维的LIS,将第一维排序后,和第一维一样

那么三维的lis怎么做了,我们很容易想到将第一维排序后分治的写,分了后, 按照y排序,怎么治呢?用树状数组更新前前x的最大值,然后再用dp更新即可

这里需要注意,和陌上花开等板子题不一样,我们这里不能分了左半部分后再直接分右半部分,这个地方卡了我好久。这里的分治运用是用来给dp服务的,我们dp是由前面的状态转移过来,所以,我们要先更新左半边后再去分治右半边

代码:

#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int mod = 1 << 30;
int n;
struct P {
int x, y, z, id;
} point[maxn], now[maxn];
struct A {
int max, sum;
} ans[maxn], tr[maxn];
bool cmpx(const P a, const P b) {
return a.x < b.x;
}
bool cmpy(const P a, const P b) {
return a.y < b.y;
}
bool cmpz(const P a, const P b) {
return a.z < b.z;
} int lowbit(int x) {
return (x & -x);
} void insert(int x, A tmp) {
for(int i = x; i <= n; i += lowbit(i)) {
if(tr[i].max == tmp.max) {
tr[i].sum += tmp.sum;
tr[i].sum %= mod;
} else if(tr[i].max < tmp.max) {
tr[i].sum = tmp.sum;
tr[i].max = tmp.max;
}
}
} A getsum(int x) {
A ret;
ret.max = -1;
for(int i = x; i >= 1; i -= lowbit(i)) {
if(tr[i].max > ret.max) {
ret.max = tr[i].max;
ret.sum = tr[i].sum;
} else if(tr[i].max == ret.max) {
ret.sum += tr[i].sum;
ret.sum %= mod;
}
}
return ret;
} void clear(int x) {
for(int i = x; i <= n; i += lowbit(i)) {
tr[i].max = 0;
tr[i].sum = 0;
}
} void solve(int l, int r) {
if(l == r) return ;
int mid = l + r >> 1;
solve(l, mid);
for(int i = mid + 1; i <= r; i++)
now[i] = point[i];
sort(point + l, point + mid + 1, cmpz);
sort(point + mid + 1, point + r + 1, cmpz);
for(int i = mid + 1, top = l; i <= r; i++) {
while(top <= mid && point[top].z <= point[i].z) {
insert(point[top].x, ans[point[top].id]);
top++;
}
A ret = getsum(point[i].x);
ret.max++;
if(ret.max == ans[point[i].id].max) {
ans[point[i].id].sum += ret.sum;
ans[point[i].id].sum %= mod;
} else if(ret.max > ans[point[i].id].max) {
ans[point[i].id] = ret;
}
}
for(int i = l; i <= mid; i++) clear(point[i].x);
for(int i = mid + 1; i <= r; i++)
point[i] = now[i]; solve(mid + 1, r);
}
//dp[i]=max(dp[i-1],dp[j]+1)
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d %d %d", &point[i].x, &point[i].y, &point[i].z);
point[i].id = i;
}
sort(point + 1, point + 1 + n, cmpx);
for(int i = 1, xx = point[1].x - 1, num = 0; i <= n; i++) {
if(point[i].x != xx) num++, xx = point[i].x;
point[i].x = num;
}
sort(point + 1, point + 1 + n, cmpy); for(int i = 1; i <= n; i++) {
ans[i].max = 1;
ans[i].sum = 1;
}
solve(1, n);
A ret;
ret.max = -1;
for(int i = 1; i <= n; i++) {
if(ret.max == ans[i].max) {
ret.sum += ans[i].sum;
ret.sum %= mod;
} else if(ret.max < ans[i].max) {
ret = ans[i];
}
}
printf("%d %d\n", ret.max, ret.sum);
}
return 0;
}

HDU4742 CDQ分治,三维LIS的更多相关文章

  1. BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

    Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...

  2. 洛谷P3810 陌上花开 CDQ分治(三维偏序)

    好,这是一道三维偏序的模板题 当然没那么简单..... 首先谴责洛谷一下:可怜的陌上花开的题面被无情的消灭了: 这么好听的名字#(滑稽) 那么我们看了题面后就发现:这就是一个三维偏序.只不过ans不加 ...

  3. 【算法】CDQ分治 -- 三维偏序 & 动态逆序对

    初次接触CDQ分治,感觉真的挺厉害的.整体思路即分而治之,再用之前处理出来的答案统计之后的答案. 大概流程是(对于区间 l ~ r): 1.处理 l ~mid, mid + 1 ~ r 的答案: 2. ...

  4. NEUOJ 1702:撩妹全靠魅力值(CDQ分治三维偏序)

    http://acm.neu.edu.cn/hustoj/problem.php?id=1702 思路:三维偏序模板题,用CDQ分治+树状数组或者树套树.对于三元组(x,y,z),先对x进行排序,然后 ...

  5. cdq分治·三维偏序问题

    转载自FlashHu大佬的博客CDQ分治总结(CDQ,树状数组,归并排序),在讲述部分有部分删改,用了自己的代码 CDQ分治的思想 CDQ分治是基于时间的离线分治算法.这一类分治有一个重要的思想——用 ...

  6. CDQ分治 三维偏序

    这应该是一道CDQ分治的入门题目 我们知道,二维度的偏序问题直接通过,树状数组就可以实现了,但是三维如何实现呢? 我记得以前了解过一个小故事,应该就是分治的. 一个皇帝,想给部下分配任务,但是部下太多 ...

  7. BZOJ 2244: [SDOI2011]拦截导弹 (CDQ分治 三维偏序 DP)

    题意 略- 分析 就是求最长不上升子序列,坐标取一下反就是求最长不下降子序列,比较大小是二维(h,v)(h,v)(h,v)的比较.我们不看概率,先看第一问怎么求最长不降子序列.设f[i]f[i]f[i ...

  8. BZOJ.1935.[SHOI2007]Tree园丁的烦恼(CDQ分治 三维偏序)

    题目链接 矩形查询可以拆成四个点的前缀和查询(树套树显然 但是空间不够) 每个操作表示为(t,x,y),t默认有序,对x分治,y用树状数组维护 初始赋值需要靠修改操作实现. //119964kb 43 ...

  9. BZOJ.3262.陌上花开([模板]CDQ分治 三维偏序)

    题目链接 BZOJ3262 洛谷P3810 /* 5904kb 872ms 对于相邻x,y,z相同的元素要进行去重,并记录次数算入贡献(它们之间产生的答案是一样的,但不去重会..) */ #inclu ...

随机推荐

  1. MaxCompute如何对SQL查询结果实现分页获取

    由于MaxCompute SQL本身不提供类似数据库的select * from table limit x offset y的分页查询逻辑.但是有很多用户希望在一定场景下能够使用获取类似数据库分页的 ...

  2. Android中Scroller类的分析

    今天看了一下项目中用到的ViewFlow控件,想弄明白其工作原理.从头开始分析,卡在"滚动"这儿了. 做android也快两年了,连最基本的滚动都不熟悉,真是惭愧...遂网上找资料 ...

  3. LeetCode97 Interleaving String

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. (Hard) For example,Giv ...

  4. jquery 即点即改

    //在html中建立表单. <table border=""> <th>编号</th> <th>用户名</th> < ...

  5. TensorFlow 中的卷积网络

    TensorFlow 中的卷积网络 是时候看一下 TensorFlow 中的卷积神经网络的例子了. 网络的结构跟经典的 CNNs 结构一样,是卷积层,最大池化层和全链接层的混合. 这里你看到的代码与你 ...

  6. HTML的基本结构和标签分类

    HTML:超文本标记语言 HTML基本结构 <!DOCTYPE html> <html> <head> <meta charset="utf-8&q ...

  7. 基于jquery读取input上传的文件内容

    <script src="/static/js/jquery.js"></script> // 前端页面实现头像预览 // 当用户选中文件之后,也就是头像的 ...

  8. Codeforces Round #170 (Div. 1 + Div. 2)

    A. Circle Line 考虑环上的最短距离. B. New Problem \(n\) 个串建后缀自动机. 找的时候bfs一下即可. C. Learning Languages 并查集维护可以沟 ...

  9. display常用的三种值:block、inline、inline-block

    display:block(块级元素 ) 会独占一行,多个block元素会各自新起一行.默认情况下,block元素宽度自动填满其父级宽度 display:inline(内联(行级)元素 ) 不会独占一 ...

  10. 深入java面向对象四:Java 内部类种类及使用解析(转)

    内部类Inner Class 将相关的类组织在一起,从而降低了命名空间的混乱. 一个内部类可以定义在另一个类里,可以定义在函数里,甚至可以作为一个表达式的一部分. Java中的内部类共分为四种: 静态 ...