bzoj 3295 动态逆序对 CDQ分支

容易看出ans[i]=ans[i-1]-q[i],q[i]为删去第i个数减少的逆序对。

先用树状数组算出最开始的逆序对,预处理出每个数前边比它大的和后边比它小的,就求出了q[i]的初始值。

设b[i]是第i个删除的数,pos[i]为i在数列里的位置。

对q[i]产生影响的是   1. j<i,pos[b[j]]<pos[b[i]],b[j]>b[i].  2.j<i,pos[b[j]]>pos[b[i]],b[j]<b[i].

因为是三维的,所以我们套一层cdq。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define int long long
 6 #define N 100005
 7 using namespace std;
 8 int n,m;
 9 int a[N],b[N],d[N];
10 int c[N];
11 int ans[N];int p[N];
12 int qur(int x)
13 {
14     int tp=0;
15     for(int i=x;i;i-=(i&-i))tp+=c[i];
16     return tp;
17 }
18 void add(int x,int z)
19 {
20     for(int i=x;i<=n;i+=(i&-i))c[i]+=z;
21     return ;
22 }
23 int tmp[N];int q[N];
24 bool cmp(int x,int y)
25 {
26     return p[x]<p[y];
27 }
28 void solve(int l,int r)
29 {
30     if(l==r)return ;
31     int mid=(l+r)>>1;
32     int cnt=0;
33     for(int i=l;i<=r;i++)tmp[++cnt]=b[i];
34     sort(tmp+1,tmp+cnt+1,cmp);
35     for(int i=1;i<=cnt;i++)
36     {
37         if(d[tmp[i]]<=mid)add(tmp[i],1);
38         else q[tmp[i]]-=qur(n)-qur(tmp[i]);
39     }
40     for(int i=1;i<=cnt;i++)if(d[tmp[i]]<=mid)add(tmp[i],-1);
41     for(int i=cnt;i>=1;i--)
42     {
43         if(d[tmp[i]]<=mid)add(tmp[i],1);
44         else q[tmp[i]]-=qur(tmp[i]);
45     }
46     for(int i=1;i<=cnt;i++)if(d[tmp[i]]<=mid)add(tmp[i],-1);
47     solve(l,mid);solve(mid+1,r);
48     return ;
49 }
50 signed main()
51 {
52     scanf("%lld%lld",&n,&m);
53     for(int i=1;i<=n;i++)scanf("%lld",&a[i]),p[a[i]]=i;
54     for(int i=1;i<=m;i++)scanf("%lld",&b[i]),d[b[i]]=i;
55     for(int i=1;i<=n;i++)
56     {
57         int tp=qur(n)-qur(a[i]);
58         ans[0]+=tp;
59         q[a[i]]+=tp;
60         add(a[i],1);
61     }
62     memset(c,0,sizeof(c));
63     for(int i=n;i>=1;i--)
64     {
65         int tp=qur(a[i]);
66         q[a[i]]+=tp;
67         add(a[i],1);
68     }
69     memset(c,0,sizeof(c));
70     solve(1,m);
71     for(int i=1;i<m;i++)ans[i]=ans[i-1]-q[b[i]];
72     for(int i=0;i<m;i++)printf("%lld\n",ans[i]);
73     return 0;
74 }
时间: 2024-12-17 16:42:50

bzoj 3295 动态逆序对 CDQ分支的相关文章

BZOJ 3295 动态逆序对

调了好久.... 转化成三维偏序,cdq处理. 好像比较快? #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 300500 using namespace std; long long n,m,x,a[maxn],pos[maxn],f1[maxn],f2[maxn],t[maxn],ans=0; struct pnt { long

P3157 动态逆序对 CDQ分治

动态逆序对 CDQ分治 传送门:https://www.luogu.org/problemnew/show/P3157 题意: 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. 题解: 这个题是告诉你如何将一个问题转换为三维偏序问题 首先,求解逆序对,那么a.val>b.val,删除一个元素的时间是t,a.t<b.t,这个元素对应的原序列中的位置为

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

[BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数.以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. Output 输出包含m行,依次为删除每个元素之前,逆序对的

P3157 [CQOI2011]动态逆序对 (CDQ解决三维偏序问题)

P3157 [CQOI2011]动态逆序对 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. 输入格式 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数.以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. 输出格式 输出包含m行,依次为删除每个元素之前,逆序对的个数. 输入输出样例 输入

BZOJ 3295: [Cqoi2011]动态逆序对 cdq分治

https://www.lydsy.com/JudgeOnline/problem.php?id=3295 这个妹妹我曾见过的~~~ 之前应该在校内oj写了,似乎还写过题解?发现没写博客就重新水一遍代码水一篇博客好了. 把找逆序对的过程想成一个一个往里塞数字然后找每个数字可以组成的逆序对,把最后要去掉的几个也想成往里塞,所以加一个时间维度用cdq求三维偏序. 1 #include<iostream> 2 #include<cstdio> 3 #include<algorith

P3157 [CQOI2011]动态逆序对(CDQ分治)

题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. 输入格式 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数.以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. 输出格式 输出包含m行,依次为删除每个元素之前,逆序对的个数. 输入输出样例 输入 #1复制 5 4 1 5 3 4 2 5 1

LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)

传送门 解题思路 cdq分治,将位置看做一维,修改时间看做一维,权值看做一维,然后就转化成了三维偏序,用排序+cdq+树状数组.注意算删除贡献时要做两次cdq,分别算对前面和后面的贡献. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 100005; const int MAXM =

主席树初探 &amp; bzoj 3295: [Cqoi2011] 动态逆序对 题解

[原题] 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 778  Solved: 263 [Submit][Status] Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元

【BZOJ 3295】 [Cqoi2011]动态逆序对

3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1373  Solved: 465 [Submit][Status][Discuss] Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数