[BZOJ 3262]陌上开花
今天写了到偏序问题,发现博主真的是个傻X
以前的写法
/************************************************************** Problem: 3262 User: MiEcoku Language: C++ Result: Accepted Time:3416 ms Memory:6296 kb ****************************************************************/ #include <cstdio> #include <algorithm> using namespace std; #define mid ( l + r >> 1) #define lowbit(x) ( x & -x) struct GG { int x, y, z, id, w; void get () { scanf("%d%d%d", &x, &y, &z); } }a[], b[]; ], k; ; ; x -= lowbit(x)) ans += dis[x]; return ans; } void add(int x, int y) { for ( ; x <= k; x += lowbit(x)) dis[x] += y; } bool cmp1(GG a, GG b) { return a.x < b.x || (a.x == b.x && a.y < b.y) || (a.x == b.x && a.y == b.y && a.z < b.z); } bool cmp2(GG a, GG b) { return a.y < b.y || (a.y == b.y && a.z < b.z); } ]; void cdq(int l, int r) { , r); sort(b+l, b+mid+, cmp2); sort(b+mid+, b+r+, cmp2); ; for ( int i = l; i <= mid; i ++) { while( b[q].y < b[i].y && q <= r) ans[b[q].id] += query(b[q].z), q ++; add(b[i].z, b[i].w); } while( q <= r) ans[b[q].id] += query(b[q].z), q ++; for ( int i = l; i <= mid; i ++) add(b[i].z, -b[i].w); } ]; int main() { scanf("%d%d", &_, &k); ; i <= _; i ++) a[i].get(); sort( a+, a++_, cmp1); ; i <= _; i ++) { cnt ++; ].x || a[i].y != a[i+].y || a[i].z != a[i+].z) b[++ n] = a[i], b[n].w = cnt, cnt = , b[n].id = n; } cdq(, n); ; i <= n; i ++) d[ans[b[i].id]+b[i].w-] += b[i].w; ; i < _; i ++) printf("%d\n", d[i]); }
可以看出这是个n * logn^2 的算法,这也是博主在大多数地方看到的写法,结果傻叉的以为cdq就是n * long n ^ 2 的算法
实际上可不可以更快?
void cdq(int l, int r) { , r); sort(b+l, b+mid+, cmp2); sort(b+mid+, b+r+, cmp2); ; for ( int i = l; i <= mid; i ++) { while( b[q].y < b[i].y && q <= r) ans[b[q].id] += query(b[q].z), q ++; add(b[i].z, b[i].w); } while( q <= r) ans[b[q].id] += query(b[q].z), q ++; for ( int i = l; i <= mid; i ++) add(b[i].z, -b[i].w); }
可以看出,在cdq内部排了个序,然而真的有这个必要吗? 答案是否定的
我们都知道归并排序,可以看出,内部这个排序无非是想要将第二位排序
但在内部这个循环内就已经排序,所以那个排序可以省略
我们新开个数组
void cdq(int l, int r) { , r); , cnt = ; for ( int i = l; i <= mid; i ++) { while( b[q].y < b[i].y && q <= r) ans[b[q].id] += query(b[q].z), T[++ cnt] = b[q], q ++; add(b[i].z, b[i].w); T[++ cnt] = b[i]; } while( q <= r) ans[b[q].id] += query(b[q].z), T[++ cnt] = b[q], q ++; for ( int i = l; i <= mid; i ++) add(b[i].z, -b[i].w); cnt = ; for ( int i = l; i <= r; ++ i) b[i] = T[++ cnt]; }
这样,我们就省略了内部的一个排序问题,做到n * long n
还能再快不?
能!
for ( int i = l; i <= mid; i ++) add(b[i].z, -b[i].w);
对于这句话,我们能不能将它优化掉?
我们考虑加入一个时间戳 tim
int query(int x, int K) { ; ; x -= lowbit(x)) if( mark[x] == K) ans += dis[x]; return ans; } void add(int x, int y, int K) { for ( ; x <= k; x += lowbit(x)) if( mark[x] == K) dis[x] += y; else mark[x] = K, dis[x] = y; }
然后对树状数组进行点修改
这样我们就将常数再次优化了下
上总代码
/************************************************************** Problem: 3262 User: MiEcoku Language: C++ Result: Accepted Time:1428 ms Memory:9028 kb ****************************************************************/ /************************************************************** Problem: 3262 User: MiEcoku Language: C++ Result: Accepted Time:3416 ms Memory:6296 kb ****************************************************************/ #include <cstdio> #include <algorithm> using namespace std; #define mid ( l + r >> 1) #define lowbit(x) ( x & -x) struct GG { int x, y, z, id, w; void get () { scanf("%d%d%d", &x, &y, &z); } }a[], b[], T[]; ], k, tim, mark[]; int query(int x, int K) { ; ; x -= lowbit(x)) if( mark[x] == K) ans += dis[x]; return ans; } void add(int x, int y, int K) { for ( ; x <= k; x += lowbit(x)) if( mark[x] == K) dis[x] += y; else mark[x] = K, dis[x] = y; } bool cmp1(GG a, GG b) { return a.x < b.x || (a.x == b.x && a.y < b.y) || (a.x == b.x && a.y == b.y && a.z < b.z); } bool cmp2(GG a, GG b) { return a.y < b.y || (a.y == b.y && a.z < b.z); } ]; void cdq(int l, int r) { , r); , cnt = ; ++ tim; for ( int i = l; i <= mid; i ++) { while( b[q].y < b[i].y && q <= r) ans[b[q].id] += query(b[q].z, tim), T[++ cnt] = b[q], q ++; add(b[i].z, b[i].w, tim); T[++ cnt] = b[i]; } while( q <= r) ans[b[q].id] += query(b[q].z, tim), T[++ cnt] = b[q], q ++; cnt = ; for ( int i = l; i <= r; ++ i) b[i] = T[++ cnt]; } ]; int main() { scanf("%d%d", &_, &k); ; i <= _; i ++) a[i].get(); sort( a+, a++_, cmp1); ; i <= _; i ++) { cnt ++; ].x || a[i].y != a[i+].y || a[i].z != a[i+].z) b[++ n] = a[i], b[n].w = cnt, cnt = , b[n].id = n; } cdq(, n); ; i <= n; i ++) d[ans[b[i].id]+b[i].w-] += b[i].w; ; i < _; i ++) printf("%d\n", d[i]); }
博主因为傻逼不知道这么写然后考试写的KT-tree被卡了
[BZOJ 3262]陌上开花的更多相关文章
- bzoj 3262 陌上花开 - CDQ分治 - 树状数组
Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...
- BZOJ.3262.陌上花开([模板]CDQ分治 三维偏序)
题目链接 BZOJ3262 洛谷P3810 /* 5904kb 872ms 对于相邻x,y,z相同的元素要进行去重,并记录次数算入贡献(它们之间产生的答案是一样的,但不去重会..) */ #inclu ...
- Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治
Luogu 3810 & BZOJ 3263 陌上花开/三维偏序 | CDQ分治 题面 \(n\)个元素,每个元素有三个值:\(a_i\), \(b_i\) 和 \(c_i\).定义一个元素的 ...
- 【BZOJ 3262】 3262: 陌上花开 (CDQ分治)
3262: 陌上花开 Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A ...
- BZOJ 3262 陌上花开 ——CDQ分治
[题目分析] 多维问题,我们可以按照其中一维排序,然后把这一维抽象的改为时间. 然后剩下两维,就像简单题那样,排序一维,树状数组一维,按照时间分治即可. 挺有套路的一种算法. 时间的抽象很巧妙. 同种 ...
- bzoj 3262 陌上花开
本质是一个三维偏序,一位排序后cdq分治,一维在子函数里排序,一维用树状数组维护. 把三维相等的合并到一个里面. #include<iostream> #include<cstdio ...
- BZOJ 3262 陌上花开 CDQ分治
= =原来复杂度还是nlog^2(n) Orz 被喷了 #include<cstdio> #include<cstdlib> #include<algorithm> ...
- BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]
Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...
- 【刷题】BZOJ 3262 [HNOI2008]GT考试
Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字. 他的不吉利数学A1A2...Am(0< ...
随机推荐
- CentOS7 启动docker.service失败(code=exited, status=1/FAILURE)
启动报错 Job for docker.service failed because the control process exited with error code. See "sys ...
- 【bzoj1565】[NOI2009]植物大战僵尸
1565: [NOI2009]植物大战僵尸 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2164 Solved: 1001[Submit][Stat ...
- libevent源码深度剖析一
libevent源码深度剖析一 ——序幕 张亮 1 前言 Libevent是一个轻量级的开源高性能网络库,使用者众多,研究者更甚,相关文章也不少.写这一系列文章的用意在于,一则分享心得:二则对libe ...
- fail-fast 与 fail-save 机制的区别
link:https://blog.csdn.net/bigtree_3721/article/details/67095084
- Linux问题:开启网关
1 开启网关 1.1 问题描述 虚拟机每次重启后,都需要利用 ifup eth0 来手动开启网关,否则获取到的IP地址为回环127.0.0.1 1.2 解决办法 修改ifcfg-eth0中 ONBOO ...
- 无返回值的函数如何捕获出错情况(检查errno常量)
在执行这个函数前,先清除errno,函数返回时,检查errno常量. 每次程序调用失败的时候,系统会自动用用错误代码填充errno这个全局变量,这样你只需要读errno这个全局变量就可以获得失败原因了 ...
- 数字图像处理实验(16):PROJECT 06-03,Color Image Enhancement by Histogram Processing 标签: 图像处理MATLAB 2017
实验要求: Objective: To know how to implement image enhancement for color images by histogram processing ...
- 用TCGA数据库分析癌症和癌旁组织的表达差异
上周收到一条求助信息:“如何用TCGA数据库分析LINC00152在卵巢癌与正常组织的的表达差异?” 所以以这个题目为记录分析过程如下: 一.下载数据 a)进入网站https://cancergeno ...
- urllib2设置代理
#coding=utf-8 #公司网络只有连接vpn跳板机才能使用该模块 import urllib2 proxy_handler=urllib2.ProxyHandler({'http':'http ...
- Ubuntu 14.04 安装配置强大的星际译王(stardict)词典
转载http://blog.csdn.net/huyisu/article/details/53437931