初学CDQ分治-NEU1702
关于CDQ分治,首先需要明白分治的复杂度。
T(n) = 2T(n/2)+O(kn), T(n) = O(knlogn)
T(n) = 2T(n/2)+O(knlogn), T(n) = O(knlog^2n)
T(n) = 2T(n/2)+O(k), T(n) = O(kn)
那么我们要处理[l, r]内的询问,我们可以分别处理[l, m]和[m+1, r]的询问,然后以较小的复杂度计算出[l, m]对[m+1, r]的贡献。
最简单的cdq就是三维偏序问题。
两点(x1, y1, z1)和(x2, y2, z2),同时满足x1 < x2, y1 < y2, z1 < z2,则前面的点小于后面的点。
首先按第一维x排序。
则处理的问题变成对于排在前面的点,统计多少个点满足y维与z维同时小于该点。
CDQ分治。
假设已处理出[l, m]与[m+1, r]。对于[m+1, r]内的所有点,我们还要统计[l, m]内有多少个点相比它更小。
对[l, r]按y维排序,对z维用树状数组统计。
扫描一遍排序后的[l, r]。
若该点在排序前属于[l, m],树状数组单点修改;否则该点在排序前属于[m+1, r],统计一次。
复杂度为O(nlognlogn)
CDQ分治算法的核心就在于:去掉时间的限制,将所有查询要求发生的时刻同化,化动态修改为静态查询
(其实对于有些问题来说可以把某一维的限制通过排序看作时间限制然后运用CDQ分治)
这类分治的特殊性在于分治的左右两部分的合并,作用两部分在合并的时候作用是不同的,比如,通过左半部分的影响来更新右半部分,所以分治开始前都要按照某一个关键字排序,然后利用这个顺序,考虑一个区间[l, r]的两部分间的影响。
框架为
void cdq(int l, int r){
if(l == r) return ;
int m = (l+r)/;
cdq(l, m);
cdq(m+, r); //统计[l, m]对[m+1, r]的贡献。整体排序后统计。
sort(pp+l, pp+r+, yzx);
for(int i = l; i <= r; i++)
if(pp[i].x <= m)
add(pp[i].z, );
else
ans[ pp[i].n ] += sum(pp[i].z);
for(int i = l; i <= r; i++)
if(pp[i].x <= m)
add(pp[i].z, -);
}
题意:一个人的魅力值是相对于周围人来说的,如果他的颜值,内涵和智慧值同时不低于另外一个人,那么他的魅力值就会加1,给你一些人的颜值,内涵,和智慧值,请输出这些人的魅力值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+;
struct p{
int n, x, y, z;
p(){}
p(int n, int x, int y, int z): n(n), x(x), y(y), z(z){}
bool operator <(const p& A) const{
if(x != A.x) return x < A.x;
return y != A.y? y < A.y: z < A.z;
}
bool operator ==(const p& A) const{
return x == A.x&&y == A.y&&z == A.z;
}
};
bool yzx(p A, p B){//y z x
if(A.y != B.y) return A.y < B.y;
return A.z != B.z? A.z < B.z : A.x < B.x;
}
bool cmpn(p A, p B){//n
return A.n < B.n;
}
p pp[maxn]; int c[maxn], Maxn;
int lowbit(int x){ return x&-x;}
int add(int x, int d){
for(int i = x; i <= Maxn; i += lowbit(i))
c[i] += d;
}
int sum(int x){
int ret = ;
for(int i = x; i; i -= lowbit(i))
ret += c[i];
return ret;
} int ans[maxn]; void cdq(int l, int r){
if(l == r) return ;
int m = (l+r)/;
cdq(l, m);
cdq(m+, r);
sort(pp+l, pp+r+, yzx);
for(int i = l; i <= r; i++)
if(pp[i].x <= m)
add(pp[i].z, );
else
ans[ pp[i].n ] += sum(pp[i].z);
for(int i = l; i <= r; i++)
if(pp[i].x <= m)
add(pp[i].z, -);
} int same[maxn];// smae[i] 表示 下标为i的ans 与 下标为same[i]相同 int main(){
int T; scanf("%d", &T);
while(T--){
int n;scanf("%d", &n);
for(int i = ; i < n ; i++){
pp[i].n = i;
scanf("%d%d%d", &pp[i].x, &pp[i].y, &pp[i].z);
Maxn = max(pp[i].z, Maxn);
}
sort(pp, pp+n);//x y z for(int i = ; i < n; ){
int j = i+;
while(j < n&&pp[i] == pp[j]) j++;
while(i < j)
same[ pp[i++].n ] = pp[j-].n;
}
for(int i = ; i < n; i++)
pp[i].x = i; memset(ans, , sizeof(int)*(n+) );
cdq(, n-); sort(pp, pp+n, cmpn);
for(int i = ; i < n; i++)
printf("%d\n", ans[ same[ pp[i].n ] ]);
}
return ; }
初学CDQ分治-NEU1702的更多相关文章
- 初学cdq分治学习笔记(可能有第二次的学习笔记)
前言骚话 本人蒟蒻,一开始看到模板题就非常的懵逼,链接,学到后面就越来越清楚了. 吐槽,cdq,超短裙分治....(尴尬) 正片开始 思想 和普通的分治,还是分而治之,但是有一点不一样的是一般的分治在 ...
- ACdream1157 Segments(CDQ分治 + 线段树)
题目这么说的: 进行如下3种类型操作:1)D L R(1 <= L <= R <= 1000000000) 增加一条线段[L,R]2)C i (1-base) 删除第i条增加的线段, ...
- 「分治」-cdq分治
cdq分治是一种分治算法: 一种分治思想,必须离线,可以用来处理序列上的问题(比如偏序问题),还可以优化1D/1D类型的DP.• 算法的大体思路我们可以用点对来描述.假定我们有一个长度为n的序列,要处 ...
- CDQ分治&整体二分学习个人小结
目录 小结 CDQ分治 二维LIS 第一道裸题 bzoj1176 Mokia bzoj3262 陌上花开 bzoj 1790 矩形藏宝地 hdu5126四维偏序 P3157 [CQOI2011]动态逆 ...
- 【教程】简易CDQ分治教程&学习笔记
前言 辣鸡蒟蒻__stdcall终于会CDQ分治啦! CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. CDQ分治的基 ...
- BZOJ 2683 简单题 ——CDQ分治
[题目分析] 感觉CDQ分治和整体二分有着很本质的区别. 为什么还有许多人把他们放在一起,也许是因为代码很像吧. CDQ分治最重要的是加入了时间对答案的影响,x,y,t三个条件. 排序解决了x ,分治 ...
- HDU5618 & CDQ分治
Description: 三维数点 Solution: 第一道cdq分治...感觉还是很显然的虽然题目不能再傻逼了... Code: /*=============================== ...
- 初识CDQ分治
[BZOJ 1176:单点修改,查询子矩阵和]: 1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 200 ...
- HDU5322 Hope(DP + CDQ分治 + NTT)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5322 Description Hope is a good thing, which can ...
随机推荐
- 在discuz二次开发模板时,diy编辑显示我“抱歉,您没有权限添加此模块
<div id="diy_vk_portal_slide_top" class="area"><div id="frameCRxR0 ...
- ecshop后台增加模块菜单详细教程(图)
我们有时候针对ecshop如此开发,想在后台加一些菜单,最模板以前提供过教程,但是并非很系统,今天最模板抛砖引玉图文教程告诉大家:如何在ecshop后台增加模块菜单! 首先需要修改四个文件:inc_p ...
- 5.toogleButton以及Switch
Switch现在用得更多,比toogleButton界面美观,用户体验也要好. 点击事件: 用isChecked来判断点击的是哪一个,然后做相对应的回应.
- java 1G大文件复制
对比几种复制方法 复制的文件是980m的txt文件 1. FileChannel 方法 代码: public static void mappedBuffer() throws IOExceptio ...
- JSTL.带标签体的标签,方法和例子
1. 实现 forEach 标签: 两个属性: items(集合类型, Collection), var(String 类型) doTag: 遍历 items 对应的集合 把正在遍历的对象放入到 pa ...
- Eclipse编译器及一些jdk + notepad
Eclipse32位系统 http://pan.baidu.com/s/1i3eU8V7 Eclipse64位系统 http://pan.baidu.com/s/1i36ERCp jdk64位 htt ...
- linux里用cmake安装的软件要怎么卸载?
找到make install之后产生的这个文件install_manifest.txt 这里在build文件里面有一个 install_manifest.txt,在里面有安装的所有东西的路径,删除它们 ...
- 批量清除.svn 或 _svn
Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN]@=&q ...
- 编译android源码官方教程(5)编译完之后刷机、编译fastboot
Running Builds IN THIS DOCUMENT Building fastboot and adb Booting into fastboot mode Unlocking the b ...
- Python 2.7.9 Demo - 三元表达式
#coding=utf-8 #!/usr/bin/python import logging; a = 'abc'; print 'Y' if isinstance(a, str) else 'N';