深谈CDQ分治
关于CDQ分治我想我自己做过前面的题应该会了这种思想了吧,然后我是真的“会了”。
我想针对于偏序问题我是会了,我现在只会三维偏序了,脑子都是疼的。
但是 CDQ分治最主要的还是基于时间方面的分治思想,所以呢,偏序问题没那么重要了。
关键是分治!分治(敲黑板)不是偏序!
下面我们再来几道偏序。。。


这道题呢 暴力修改+n^2求和 肯定炸了,但是细节注意到拿到题先分析爆long long么
每次都是单点修改所以 2e5*2e3=4e8不会炸呢。
想一下如果我们把整个矩阵便利一遍 超时 我们生成整个矩阵爆空间。
所以需要转换问题 针对每个点都是坐标 x,y 以及该操作的时间 t
为什么是三个元素啊 这不是三维偏序么?但是对于查询呢 一起放里面不就好了。
这里求一个矩阵的和我们需要将其转换一下,要不然怎么求
转换成 大矩阵的和减去2个小矩阵的和+最小矩阵的和不就行了么。解决了问题。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void put(int x)
{
x<?putchar('-'),x=-x:;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar();return;
}
const int MAXN=;
struct wy
{
int x,y,z;
int v,k;
}t[MAXN],tmp[MAXN];//三维偏序问题
int c[MAXN];
int n,cnt,num,ans[MAXN];
int cmp(wy x,wy y)
{
if(x.x==y.x)
{
if(x.y==y.y)return x.v<y.v;
return x.y<y.y;
}
return x.x<y.x;
}
int cmp1(wy x,wy y)
{
return x.v<y.v;
}
void add(int x,int y)
{
for(;x<=num;x+=x&(-x))c[x]+=y;
}
int ask(int x)
{
int cnt=;
for(;x;x-=x&(-x))cnt+=c[x];
return cnt;
}
void CDQ(int l,int r)
{
if(l==r)return;
int mid=(l+r)>>;
CDQ(l,mid);
CDQ(mid+,r);
int i=l,j=mid+;
for(int k=l;k<=r;k++)
{
if(j>r||(i<=mid&&t[i].y<=t[j].y))add(t[i].v,t[i].z),tmp[k]=t[i],i++;
else
{
ans[t[j].v]+=ask(t[j].v);
tmp[k]=t[j];
j++;
}
}
for(int k=l;k<=mid;k++)add(t[k].v,-t[k].z);
for(int k=l;k<=r;k++)t[k]=tmp[k];
return;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();
while()
{
int p,x,y,z,u1,u2;
p=read();
if(p==)break;
++cnt;
x=read();y=read();
if(p==)
{
z=read();
t[++num].x=x,t[num].y=y,t[num].z=z;
t[num].v=cnt;
}
if(p==)
{
u1=read();u2=read();
t[++num].x=min(u1-,x-);t[num].y=max(u2,y);
t[num].v=cnt++;t[num].k++;
t[++num].x=max(u1,x);t[num].y=min(u2-,y-);
t[num].v=cnt++;t[num].k++;
t[++num].x=min(u1-,x-);t[num].y=min(u2-,y-);
t[num].v=cnt++;t[num].k++;
t[++num].x=max(u1,x);t[num].y=max(u2,y);
t[num].v=cnt;t[num].k++;
}
}
sort(t+,t++num,cmp);
//for(int i=1;i<=num;i++)cout<<t[i].x<<' '<<t[i].y<<endl;
CDQ(,num);
sort(t+,t++num,cmp1);
for(int i=;i<=num;i++)
{
if(t[i].k!=)
{
int xx=ans[t[i].v];
int yy=ans[t[i+].v];
int zz=ans[t[i+].v];
int uu=ans[t[i+].v];
put(uu-xx-yy+zz);
i+=;
}
}
return ;
}
关键是思想思想 不是三维偏序!!!(说了是CDQ的思想)
下面再来一道三维偏序问题:

这道题呢 很迷的我迷了一晚上加一下午 加一中午。
听学长讲的博弈论都不想听一直在想如何统计答案。
时间戳这个我是想出来了,但是三维偏序如何统计答案呢,我迷了一波。
因为CDQ我光想着CDQ分治左边只会对右边进行累加却没想到啊,这个数字消失之时右边也会对其有价值累加。
我却一直在被CDQ左边只会对右边有贡献搞乱了,貌似不知道逆序对的性质了。
哎 惭愧其实我是能想出来的,但是思想一直不在正轨上最后被学长拉回来了。
这道题其实需要统计两遍然后 左边对右边的贡献和右边对左边的贡献。
关键是知道自己在写什么数据存到了哪里,哪里是答案 求出来的东西是什么这几点很重要!
统计两遍很显然吧,然后时间戳相等的将会被累加两次需要减去一次即可。
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline long long read()
{
long long x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(long long x)
{
x<?putchar('-'),x=-x:;
long long num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar();return;
}
const long long MAXN=;
struct wy
{
long long x,y,t;
}t[MAXN],tmp[MAXN];
long long n,m,c[MAXN];
long long q[MAXN],h,num[MAXN],cnt,x,sum[MAXN],pos[MAXN],cnt1;
long long cmp(wy x,wy y){return x.x>y.x;}
void add(long long x,long long y){for(;x;x-=x&(-x))c[x]+=y;}
void add1(long long x,long long y){for(;x<=MAXN;x+=x&(-x))c[x]+=y;}
long long ans[MAXN];
long long ask(long long x)
{
long long cnt=;
for(;x<=MAXN;x+=x&(-x))cnt+=c[x];
return cnt;
}
long long ask1(long long x)
{
long long cnt=;
for(;x;x-=x&(-x))cnt+=c[x];
return cnt;
}
void CDQ(long long l,long long r)
{
if(l==r)return;
long long mid=(l+r)>>;
CDQ(l,mid);
CDQ(mid+,r);
long long i=l,j=mid+;
for(long long k=l;k<=r;k++)//左边给右边贡献小t累加大t贡献
{
if(j>r||(t[i].t>=t[j].t&&i<=mid))tmp[k]=t[i],add(t[i].y,),i++;
else
{
sum[t[j].t]+=ask(t[j].y);
tmp[k]=t[j];
j++;
}
}
for(long long k=l;k<=mid;k++)add(t[k].y,-);
for(long long k=l;k<=r;k++)t[k]=tmp[k];
return;
}
void CDQ1(long long l,long long r)
{
if(l==r)return;
long long mid=(l+r)>>;
CDQ1(l,mid);
CDQ1(mid+,r);
long long i=l,j=mid+;
for(long long k=l;k<=r;k++)//左边给右边贡献小t累加大t贡献
{
if(j>r||(t[i].t>=t[j].t&&i<=mid))tmp[k]=t[i],add1(t[i].y,),i++;
else
{
sum[t[j].t]+=ask1(t[j].y);
tmp[k]=t[j];
j++;
}
}
for(long long k=l;k<=mid;k++)add1(t[k].y,-);
for(long long k=l;k<=r;k++)t[k]=tmp[k];
return;
}
void yy()
{
for(long long i=h;i>=;i--)
{
cnt1+=ask1(q[i]-);
add1(q[i],);
}
return;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();
for(long long i=;i<=n;i++)
{
x=read();
t[i].x=i;
t[i].y=x;
pos[x]=i;
}
for(long long i=;i<=m;i++)x=read(),num[pos[x]]=++cnt;
for(long long i=;i<=n;i++)
{
if(num[i]!=)t[i].t=num[i];
else q[++h]=t[i].y,t[i].t=cnt+;
}
//for(long long i=1;i<=n;i++)cout<<t[i].x<<' '<<t[i].y<<' '<<t[i].t<<endl;
CDQ(,n);
//for(long long i=1;i<=cnt;i++)put(sum[i]);
sort(t+,t++n,cmp);
CDQ1(,n);
yy();
//cout<<cnt1<<endl;
for(long long i=cnt+;i>=;i--)ans[i]=sum[i]+ans[i+];
for(long long i=;i<=cnt;i++)put(ans[i]-cnt1);
return ;
}
没有梦想 何必远方?
深谈CDQ分治的更多相关文章
- 浅谈CDQ分治与偏序问题
初识CDQ分治 CDQ分治是一个好东西,一直听着dalao们说所以就去学了下. CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. ...
- cdq分治浅谈
$cdq$分治浅谈 1.分治思想 分治实际上是一种思想,这种思想就是将一个大问题划分成为一些小问题,并且这些小问题与这个大问题在某中意义上是等价的. 2.普通分治与$cdq$分治的区别 普通分治与$c ...
- BZOJ1176---[Balkan2007]Mokia (CDQ分治 + 树状数组)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1176 CDQ第一题,warush了好久.. CDQ分治推荐论文: 1 <从<C ...
- BZOJ1173 CDQ分治 笔记
目录 二维数据结构->cdq 预备知识 T1: 二维树状数组 T2:cdq分治 bzoj1176 mokia:Debug心得 一类特殊的CDQ分治 附: bzoj mokia AC代码 二维数据 ...
- [Noi2014]购票 BZOJ3672 点分治+斜率优化+CDQ分治
Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会.全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的 ...
- 【BZOJ】1492: [NOI2007]货币兑换Cash(cdq分治)
http://www.lydsy.com/JudgeOnline/problem.php?id=1492 蒟蒻来学学cdq神算法啊.. 详见论文 陈丹琦<从<Cash>谈一类分治算法 ...
- CDQ分治入门
前言 \(CDQ\)分治是一个神奇的算法. 它有着广泛的用途,甚至在某些题目中还能取代\(KD-Tree\).树套树等恶心的数据结构成为正解,而且常数还小得多. 不过它也有一定的缺点,如必须离线操作, ...
- 1492: [NOI2007]货币兑换Cash【CDQ分治】
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 4166 Solved: 1736[Submit][Sta ...
- CDQ分治学习思考
先挂上个大佬讲解,sunyutian1998学长给我推荐的mlystdcall大佬的[教程]简易CDQ分治教程&学习笔记 还有个B站小姐姐讲解的概念https://www.bilibili.c ...
随机推荐
- 清除win下连接的linux的samba服务缓存 用户名和密码
1:cmd 2:在停止查看共享的情况下执行:net use * /del 删除所有 或根据列表,一个个删除连接: net use 远程连接名称 /del
- mac无法访问samba共享 提示输入用户名密码
这时候需要输入mac笔记本的用户名和密码 也可以在samba服务器上增加用用户: # smbpasswd -a user_nameNew SMB password:Retype new SMB pas ...
- python学习之struct模块
class struct.Struct(format) 返回一个struct对象(结构体,参考C). 该对象可以根据格式化字符串的格式来读写二进制数据. 第一个参数(格式化字符串)可以指定字节的顺序. ...
- 【Netty】通俗地讲,Netty 能做什么?
作者:郭无心链接:https://www.zhihu.com/question/24322387/answer/78947405来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- JAVA(五)反射机制/Annotation
成鹏致远 | lcw.cnblog.com |2014-02-04 反射机制 1.认识Class类 在正常情况下,必须知道一个类的完整路径之后才可以实例化对象,但是在 java中也允许通过一个对象来找 ...
- Python3解《剑指》问题:“遇到奇数移至最前,遇到偶数移至最后”
[本文出自天外归云的博客园] 看到一个<剑指Offer>上的问题:“遇到奇数移至最前,遇到偶数移至最后.” 我做了两种解法.一种是利用python内置函数,移动过程用了插入法,很简单.另一 ...
- Java四类八种数据类型
http://www.cnblogs.com/simplefrog/archive/2012/07/15/2592011.html 第一类:逻辑型boolean 第二类:文本型char 第三类:整数型 ...
- Python 中 __all__ 的作用(转)
之前看代码每次遇到import *时就会特别蒙,看到这篇文章一下子就弄明白了,原文地址:https://www.cnblogs.com/alamZ/p/6943869.html 1.测试文件foo.p ...
- Pytest运行测试用例的多种方式和调试
测试用例上方使用多个fixtures叠加时,是从下往上进行fixtures调用的.如果是 @pytest.mark.usefixtures('action','a','action2')这种形式,是从 ...
- PHP实现敏感词过滤系统
PHP实现敏感词过滤系统 安装说明 安装PHP扩展 trie_filter,安装教程 http://blog.41ms.com/post/39.html 安装PHP扩展 swoole,安装教程 htt ...