BZOJ3295 [Cqoi2011]动态逆序对 【CDQ分治】

本文介绍了一种利用CDQ分治算法解决逆序对动态更新问题的方法。通过对序列进行操作,在每次删除一个元素后计算剩余序列中逆序对的数量。采用三元组记录元素信息,并通过两次正反统计确保所有情况被覆盖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

对于序列A,它的逆序对数定义为满足i

输入格式

输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。

输出格式

输出包含m行,依次为删除每个元素之前,逆序对的个数。

输入样例

5 4

1

5

3

4

2

5

1

4

2

输出样例

5

2

2

1

样例解释

(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

提示

N<=100000 M<=50000

题解

反过来插入元素
对于每个元素,对应一个三元组(t,x,y),表示t时刻插入,位置x,权值y
每个元素插入时产生的逆序对数量为所有的满足如下条件的(t’,x’,y’)
t’ < t 且 x’ > x 且 y’ <y
或者 t’ < t 且 x’ < x 且 y’ > y
这就是三维偏序,可以用CDQ分治
因为有两种情况,所以要正反统计两次
压行代码50行不到,CDQ很感人】

#include<iostream>
#include<cstdio>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define lbt(x) (x & -x)
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
    while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
    return out * flag;
}
struct Que{int t,x,y;}Q[maxn],T[maxn];
inline bool operator <(const Que& a,const Que& b){return a.x > b.x;}
int N,M,A[maxn],B[maxn],C[maxn],cnt,Qi,s[maxn];
LL ans[maxn];
void add(int u,int v){while (u <= N) s[u] += v,u += lbt(u);}
int query(int u){int Ans = 0; while (u) Ans += s[u],u -= lbt(u); return Ans;}
void cdq(int l,int r){
    if (l == r) return;
    int mid = l + r >> 1,l1 = l,l2 = mid + 1;
    for (int i = l; i <= r; i++)
        if (Q[i].t <= mid) add(Q[i].y,1);
        else ans[Q[i].t] += query(Q[i].y);
    for (int i = l; i <= r; i++)
        if (Q[i].t <= mid) add(Q[i].y,-1);
    for (int i = r; i >= l; i--)
        if (Q[i].t <= mid) add(N - Q[i].y + 1,1);
        else ans[Q[i].t] += query(N - Q[i].y + 1);
    for (int i = l; i <= r; i++)
        if (Q[i].t <= mid) T[l1++] = Q[i],add(N - Q[i].y + 1,-1);
        else T[l2++] = Q[i];
    for (int i = l; i <= r; i++) Q[i] = T[i];
    cdq(l,mid); cdq(mid + 1,r);
}
int main(){
    cnt = N = read(); M = read();
    REP(i,N) B[A[i] = read()] = i;
    REP(i,M){C[Q[i].x = B[Q[i].y = read()]] = true; Q[i].t = cnt--; ++Qi;}
    REP(i,N) if (!C[i]) Q[++Qi] = (Que){cnt--,i,A[i]};
    sort(Q + 1,Q + 1 + N);
    cdq(1,N);
    REP(i,N) ans[i] += ans[i - 1];
    for (int i = 0; i < M; i++) printf("%lld\n",ans[N - i]);
    return 0;
}
内容概要:本文《2025年全球AI Coding市场洞察研究报告》由亿欧智库发布,深入分析了AI编程工具的市场现状和发展趋势。报告指出,AI编程工具在2024年进入爆发式增长阶段,成为软件开发领域的重要趋势。AI编程工具不仅简化了代码生成、调试到项目构建等环节,还推动编程方式从人工编码向“人机协同”模式转变。报告详细评估了主流AI编程工具的表现,探讨了其商业模式、市场潜力及未来发展方向。特别提到AI Agent技术的发展,使得AI编程工具从辅助型向自主型跃迁,提升了任务执行的智能化和全面性。报告还分析了AI编程工具在不同行业和用户群体中的应用,强调了其在提高开发效率、减少重复工作和错误修复方面的显著效果。最后,报告预测2025年AI编程工具将在精准化和垂直化上进一步深化,推动软件开发行业进入“人机共融”的新阶段。 适合人群:具备一定编程基础,尤其是对AI编程工具有兴趣的研发人员、企业开发团队及非技术人员。 使用场景及目标:①了解AI编程工具的市场现状和发展趋势;②评估主流AI编程工具的性能和应用场景;③探索AI编程工具在不同行业中的具体应用,如互联网、金融、游戏等;④掌握AI编程工具的商业模式和盈利空间,为企业决策提供参考。 其他说明:报告基于亿欧智库的专业研究和市场调研,提供了详尽的数据支持和前瞻性洞察。报告不仅适用于技术从业者,也适合企业管理者和政策制定者,帮助他们在技术和商业决策中更好地理解AI编程工具的价值和潜力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值