题目链接

题意

求三元组的严格上升子序列

思路

先考虑暴力\(dp\)一下

for(int i = 1;i <= n;++i)
for(int j = 1;j < i;++j)
if(x[i] > x[j] && y[i] > y[j] && z[i] > z[j])
f[i] = max(f[i],f[j] + 1)

考虑用\(CDQ\)分治优化这个\(dp\)。

大体思路是,先按照第一维排序,保证第一维是严格上升的。然后\(CDQ\)一下第二维。树状数组维护第三维(需要先离散化)。这里用到的是树状数组维护前缀最大值。

有两个\(bug\)调了很久。

bug1

直接套用了三维偏序的板子。其实这个题在\(CDQ\)的时候是不能像这样的

void cdq(int l,int r) {
if(r <= l) return;
cdq(l,mid),cdq(mid + 1,r);
//……
}

因为在\(cdq\)右边之前,必须保证右边已经从左边获取过答案了。这就是求\(LIS\)与求三维偏序不同的地方。

正确操作应该是

void cdq(int l,int r){
if(r <= l) return;
cdq(l,mid);
//……
cdq(mid + 1,r)
}

其实这个\(bug\)挺\(low\)的,感觉自己智障了2333

bug2

因为题目中说必须是严格递增的。所以\(mid\)的位置就不能直接取中间了。

需要找到一个\(x[mid]\)与\(x[mid + 1]\)不同的位置。

代码

/*
* @Author: wxyww
* @Date: 2019-02-15 10:45:05
* @Last Modified time: 2019-02-16 15:29:12
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 300000 + 10;
map<int,int>ma;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int ls[N],tree[N];
struct node {
int x[10],ans;
}a[N];
ll A,P,n;
int js;
void clear(int pos) {
while(pos <= js) {
tree[pos] = 0;
pos += pos & -pos;
}
}
void update(int pos,int x) {
while(pos <= js) {
tree[pos] = max(x,tree[pos]);
pos += pos & -pos;
}
}
int query(int pos) {
int ret = 0;
while(pos) {
ret = max(ret,tree[pos]);
pos -= pos & -pos;
}
return ret;
}
node tmp[N];
bool cmp(node x,node y) {
if(x.x[1] != y.x[1])
return x.x[1] < y.x[1];
if(x.x[2] != y.x[2]) return x.x[2] < y.x[2];
return x.x[3] < y.x[3];
}
bool cmy(node x,node y) {
if(x.x[2] != y.x[2]) return x.x[2] < y.x[2];
return x.x[3] < y.x[3];
}
void cdq(int l,int r) {
if(r <= l) return;
//保证右边第一维严格大于左边
sort(a + l,a + r + 1,cmp);
int mid = (l + r) >> 1; int tt = 1e9;
for(int i = l;i < r;++i) if(a[i].x[1] != a[i + 1].x[1] && abs(mid - i) < abs(mid - tt)) tt = i;
if(tt == 1e9) return;
mid = tt;
//保证两边第二维分别有序
cdq(l,mid);
sort(a + l,a + mid + 1,cmy);
sort(a + mid + 1,a + r + 1,cmy);
int L = l,R = mid + 1,now = l;
while(L <= mid && R <= r) {
if(a[L].x[2] <= a[R].x[2]) {
update(a[L].x[3],a[L].ans);
++L;
}
else a[R].ans = max(a[R].ans,query(a[R].x[3] - 1) + 1),++R;
}
while(R <= r) a[R].ans = max(a[R].ans,query(a[R].x[3] - 1) + 1),++R;
for(int i = l;i <= L;++i) clear(a[i].x[3]);
cdq(mid + 1,r);
}
int main() {
A = read(),P = read(),n = read();
ll now = 1;
int tot = 0;
for(int i = 1;i <= n;++i)
for(int j = 1;j <= 3;++j)
ls[++tot] = a[i].x[j] = now = now * A % P,a[i].ans = 1; sort(ls + 1,ls + tot + 1);
ma[ls[1]] = ++js;
for(int i = 2;i <= tot;++i) if(ls[i] != ls[i - 1]) ma[ls[i]] = ++js;
for(int i = 1;i <= n;++i) {
for(int j = 1;j <= 3;++j)
a[i].x[j] = ma[a[i].x[j]];
sort(a[i].x + 1,a[i].x + 4);
} cdq(1,n);
int ans = 0;
for(int i = 1;i <= n;++i) ans = max(ans,a[i].ans);
cout<<ans;
return 0;
}

bzoj2253 纸箱堆叠的更多相关文章

  1. bzoj2253纸箱堆叠(动态规划+cdq分治套树状数组)

    Description P 工厂是一个生产纸箱的工厂.纸箱生产线在人工输入三个参数 n p a , 之后,即可自动化生产三边边长为 (a mod P,a^2 mod p,a^3 mod P) (a^4 ...

  2. 【BZOJ2253】[2010 Beijing wc]纸箱堆叠 cdq分治

    [BZOJ2253][2010 Beijing wc]纸箱堆叠 Description P 工厂是一个生产纸箱的工厂.纸箱生产线在人工输入三个参数 n p a , , 之后,即可自动化生产三边边长为 ...

  3. BZOJ2253: [2010 Beijing wc]纸箱堆叠

    题解: 其实就是求三维偏序最长链.类似于三维逆序对,我们可以用树状数组套平衡树来实现. DP方程 :f[i]=max(f[j]+1) a[j]<a[i] 我们按一维排序,另一位建立树状数组,把第 ...

  4. 【BZOJ2253】纸箱堆叠 [CDQ分治]

    纸箱堆叠 Time Limit: 30 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description P 工厂是一个生产纸箱的工厂. 纸 ...

  5. 纸箱堆叠 bzoj 2253

    纸箱堆叠 (1s 128MB) box [问题描述] P 工厂是一个生产纸箱的工厂.纸箱生产线在人工输入三个参数 n, p, a 之后,即可自动化生产三边边长为 (a mod P, a^2 mod p ...

  6. BZOJ 2253: [2010 Beijing wc]纸箱堆叠

    题目 2253: [2010 Beijing wc]纸箱堆叠 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 239  Solved: 94 Descr ...

  7. BZOJ_2253_[2010 Beijing wc]纸箱堆叠 _CDQ分治+树状数组

    BZOJ_2253_[2010 Beijing wc]纸箱堆叠 _CDQ分治+树状数组 Description P 工厂是一个生产纸箱的工厂.纸箱生产线在人工输入三个参数 n p a , , 之后, ...

  8. BZOJ2253 2010 Beijing wc 纸箱堆叠 CDQ分治

    这题之前度娘上没有CDQ分治做法,gerwYY出来以后写了一个.不过要sort3遍,常数很大. gerw说可以类似划分树的思想优化复杂度,但是蒟蒻目前不会划分树(会了主席树就懒得去弄了). 嗯 将me ...

  9. 【BZOJ】2253: [2010 Beijing wc]纸箱堆叠

    题意 三维严格偏序最长链.(\(n \le 50000\)) 分析 按第一维排序然后以第二和第三维作为关键字依次加入一个二维平面,维护前缀矩形最大值. 题解 当然可以树套树....可是似乎没有随机化算 ...

随机推荐

  1. java体系结构与工作方式 《深入分析java web 技术内幕》第七章

    java体系结构与工作方式 7.1 JVM体系结构 何谓JVM JVM(Java Virtual Machine) 通过模拟一个计算机来达到一个计算机所具有的计算功能 指令集:计算机所能识别的机器语言 ...

  2. 解决jest处理es模块

    解决jest处理es模块 问题场景 项目使用jest进行测试时, 当引入外部库是es模块时, jest无法处理导致报错. Test suite failed to run Jest encounter ...

  3. 测者的测试技术笔记:揭开java method的一个秘密--巨型函数

    相信,很多人都不知道Java的Method的上限为64K.本文将超过这个上限的函数叫做巨型函数. 巨型函数的问题 1.如果代码超过了这个限制,Java编译器就报"Code too large ...

  4. MySQL 处理海量数据时的一些优化查询速度方法

    查询速度慢的原因 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O 吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6 ...

  5. ext遍历表单中所有输入项,并全部设置为只读

    baseInfoForm.getForm().getFields().each(function (field) { // 设置只读 field.setReadOnly(true); })

  6. tofixed方法 四舍五入

    tofixed方法 四舍五入 toFixed() 方法可把 Number 四舍五入为指定小数位数的数字.例如将数据Num保留2位小数,则表示为:toFixed(Num):但是其四舍五入的规则与数学中的 ...

  7. sql server 临时表(上) Tempdb概述

    一.概述 在sql server里临时表存储在TempDB库中,TempDB是一个系统数据库,它只有Simple恢复模式,也是最小日志记录操作.主要用于存放局部临时表,全局临时表,表变量,都是基于临时 ...

  8. 码农人生——从未学过Android如何开发Android App 案例讲解-第002期案例

    标题有点晃眼,本次分享是002期博文的实践故事,不会有任何代码.也不会教别人android 如何开发,类似博文已经有大批大批,而且还会有陆陆续续的人写,我写的文章,主要是经验之谈,希望总结出的一些方法 ...

  9. MySQL常用日期时间函数

    日期和时间函数: MySQL服务器中的三种时区设置: ①系统时区---保存在系统变量system_time_zone ②服务器时区---保存在全局系统变量global.time_zone ③每个客户端 ...

  10. 文本分类实战(五)—— Bi-LSTM + Attention模型

    1 大纲概述 文本分类这个系列将会有十篇左右,包括基于word2vec预训练的文本分类,与及基于最新的预训练模型(ELMo,BERT等)的文本分类.总共有以下系列: word2vec预训练词向量 te ...