[摸鱼]cdq分治 && 学习笔记
待我玩会游戏整理下思绪(分明是想摸鱼
cdq分治是一种用于降维和处理对不同子区间有贡献的离线分治算法
对于常见的操作查询题目而言,时间总是有序的,而cdq分治则是耗费\(O(logq)\)的代价使动态操作化为静态查询问题(the world!
考虑无修改的求逆序对问题
每个元素可定义为\((pos_i,val_i)\),求对每个\((pos_i,val_i)\)有多少个\((pos_j,val_j)\),满足\(pos_j<pos_i,val_j>val_i\)
cdq分治的过程就是令其中一维有序(pos),计算出贡献消除该维度的影响,后面对已遍历的元素只需得知\(val\)的关系即可
因此对于归并过程的merge中假设\([l,mid]\)和\([mid+1,r]\)的子区间已经统计完,保证了两个子区间分别有序,那只需再求左子区间对右子区间的贡献即可
比如左子区间中的下标\(p\)和右子区间中的下标\(q\)满足\(val_p>val_q\),那么可以得出\(val_{[p...mid]}>val_q\),左区间对于右区间中的\(q\)的贡献为\(mid-p+1\),统计完后继续维护大区间的有序并pushup即可
而对于有修改(既存在时间变量)的操作,我们需要维护左子区间的修改对右区间查询的影响(因为对于分治,左区间存在是右区间存在的前提),对于查询则需要标记时间的维度\(ansid\)
注意如果\(p\)和\(q\)优先越界的处理上的不同
以及区间查询时一分为二的做法
练手题 Luogu - P3374
题意:m次操作,单点更新,区间查询
我们把原数组的初始值当作插入修改来处理,时间复杂度\(O((m+n)log(m+n))\)
#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
using namespace std;
const int MAXN = 1.5e6+11;
typedef long long ll;
const ll MOD = 1e9+7;
const ll INF = 1ll<<60;
unsigned int SEED = 19260817;
ll read(){
    ll x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct QUERY{
    int pos,val,type;
    bool operator < (const QUERY &rhs) const{
        if(pos!=rhs.pos) return pos<rhs.pos;
        return type<rhs.type;
    }
}Q[MAXN],tmp[MAXN];
ll ans[MAXN];
void solve(int l,int r){
    if(l==r)return;
    int mid=l+r>>1;
    solve(l,mid);
    solve(mid+1,r);
    int p=l,q=mid+1,cnt=0;
    ll sum=0;
    while(p<=mid&&q<=r){
        if(Q[p]<Q[q]){
            if(Q[p].type==1) sum+=Q[p].val;
            tmp[++cnt]=Q[p++];
        }else{
            if(Q[q].type==2) ans[Q[q].val]-=sum;
            if(Q[q].type==3) ans[Q[q].val]+=sum;
            tmp[++cnt]=Q[q++];
        }
    }
    while(p<=mid) tmp[++cnt]=Q[p++];
    while(q<=r){
        if(Q[q].type==2) ans[Q[q].val]-=sum;
        if(Q[q].type==3) ans[Q[q].val]+=sum;
        tmp[++cnt]=Q[q++];
    }
    rep(i,1,cnt) Q[i+l-1]=tmp[i];
}
int main(){
    int m,n;
    while(cin>>n>>m){
        int cnt=0,ansid=0;
        rep(i,1,n){
            Q[++cnt].pos=i;
            Q[cnt].val=read();
            Q[cnt].type=1;
        }
        rep(i,1,m){
            int op=read();
            if(op==1){
                Q[++cnt].pos=read();
                Q[cnt].val=read();
                Q[cnt].type=1;
            }else{
                int l=read();
                int r=read();
                Q[++cnt].pos=l-1;
                Q[cnt].val=++ansid;
                Q[cnt].type=2;
                Q[++cnt].pos=r;
                Q[cnt].val=ansid;
                Q[cnt].type=3;
            }
        }
        solve(1,cnt);
        rep(i,1,ansid) println(ans[i]);
    }
    return 0;
}
[摸鱼]cdq分治 && 学习笔记的更多相关文章
- 初学cdq分治学习笔记(可能有第二次的学习笔记)
		前言骚话 本人蒟蒻,一开始看到模板题就非常的懵逼,链接,学到后面就越来越清楚了. 吐槽,cdq,超短裙分治....(尴尬) 正片开始 思想 和普通的分治,还是分而治之,但是有一点不一样的是一般的分治在 ... 
- CDQ分治学习笔记
		数据结构中的一块内容:$CDQ$分治算法. $CDQ$显然是一个人的名字,陈丹琪(NOI2008金牌女选手) 这种离线分治算法被算法界称为"cdq分治" 我们知道,一个动态的问题一 ... 
- CDQ分治学习笔记(三维偏序题解)
		首先肯定是要膜拜CDQ大佬的. 题目背景 这是一道模板题 可以使用bitset,CDQ分治,K-DTree等方式解决. 题目描述 有 nn 个元素,第 ii 个元素有 a_iai.b_ibi.c_ ... 
- 三维偏序[cdq分治学习笔记]
		三维偏序 就是让第一维有序 然后归并+树状数组求两维 cdq+cdq不会 告辞 #include <bits/stdc++.h> // #define int long long #def ... 
- CDQ分治学习思考
		先挂上个大佬讲解,sunyutian1998学长给我推荐的mlystdcall大佬的[教程]简易CDQ分治教程&学习笔记 还有个B站小姐姐讲解的概念https://www.bilibili.c ... 
- cdq分治学习
		看了stdcall大佬的博客 传送门: http://www.cnblogs.com/mlystdcall/p/6219421.html 感觉cdq分治似乎很多时候都要用到归并的思想 
- [Updating]点分治学习笔记
		Upd \(2020/2/15\),又补了一题 LuoguP2664 树上游戏 \(2020/2/14\),补了一道例题 LuoguP3085 [USACO13OPEN]阴和阳Yin and Yang ... 
- 点分治&&动态点分治学习笔记
		突然发现网上关于点分和动态点分的教程好像很少……蒟蒻开篇blog记录一下吧……因为这是个大傻逼,可能有很多地方写错,欢迎在下面提出 参考文献:https://www.cnblogs.com/LadyL ... 
- [日常摸鱼]poj1741Tree-点分治
		还有两天就要去FJWC啦- 题意:一颗无根树,$k$为给定常数,求树上距离不超过$k$的点对的数量,多组数据,$n \leq 10^4$. 应该是点分治经典题~ 一般对于无根树我们都可以把它转变成有根 ... 
随机推荐
- 一步步来用C语言来写python扩展-乾颐堂
			本文介绍如何用 C 语言来扩展 python.所举的例子是,为 python 添加一个设置字符串到 windows 的剪切板(Clipboard)的功能.我在写以下代码的时候用到的环境是:window ... 
- sed命令n,N,d,D,p,P,h,H,g,G,x解析2
			摘自: https://blog.csdn.net/xiexingshishu/article/details/50514132 sed命令n,N,d,D,p,P,h,H,g,G,x解析 2016年0 ... 
- 05 Computing GC Content
			Problem The GC-content of a DNA string is given by the percentage of symbols in the string that are ... 
- Yii2.0 多语言设置(高级版配置方法) - 新的方法
			1.设置默认语言:在mail.php配置文件加上:'language'=>'zh_CN'; 2.多语言切换 (我这边是在site控制器里面操作的所以用的'/site/language') htm ... 
- vs2015 debugger,unable to attach to application iisexpress.exe
			vs2015 unable to attach to application iisexpress.exe,没有可用的数据了 搞了一天也没解决... 
- soapUI的bug切换版本解决
			目录 文章背景 目录 运行环境及出现的问题 问题解决 说明 参考文章 版本记录 文章背景 为公司编写了一个webservice,本地测试时候是没有问题的,发布到现场之后,访问出现异常,通过切换soap ... 
- 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量
			建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ... 
- top命令查看进程列表
			top命令查看进程列表 top命令是linux下常用的性能分析工具,能实时显示系统中各个进程的资源占用状况.和win的资源管理器类似.top是一个动态显示过程,即可以通过用户按键来不断刷新当前状态,如 ... 
- APUE(4)---文件和目录 (1)
			一.引言 上一章执行I/O的基本函数(打开文件.读文件和写文件),本章将描述文件系统的其他特征和文件的性质,我们将从stat函数开始,并逐个说明stat结构的每一个成员以了解文件的所有属性.在此过程中 ... 
- Struts2的多方法动态Action
			原创 一个简单的Action里面的核心方法只有一个execute(); 定义多个核心方法的Action,有如下3种方式: 为Action配置method属性 动态方法调用 使用通配符映射方式 动态方法 ... 
