3295: [Cqoi2011]动态逆序对
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 4785 Solved: 1613
[ Submit][ Status][ Discuss]
Description
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
Input
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
Output
输出包含m行,依次为删除每个元素之前,逆序对的个数。
Sample Input
5 4
1
5
3
4
2
5
1
4
2
1
5
3
4
2
5
1
4
2
Sample Output
5
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
HINT
N<=100000 M<=50000
Source
【分析】
吼题啊...
位置(w)一个维度,权值(a)一个维度,把位置排序,权值CDQ一下,时间线(t)用树状数组统计一下
题目就是要求对于一个t0,满足t<t0,w<w0,a>a0的个数和t<t0,w>w0,a<a0的个数和...这两个做两遍CDQ分治就好了...(类似陌上花开QAQ)
昨晚肝了半晚上没肝出来...诶蠢
对了我写的CDQ自带大常数(QAQ 2000ms+)
【代码】
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=100005;
int n,m,T,num;
int to[mxn],c[mxn],tim[mxn];
ll res[mxn];
struct node
{
int a,w,t;
}p[mxn],tmp[mxn];
inline bool comp(node x,node y)
{
return x.w<y.w;
}
inline int lowbit(int x) {return x&-x;}
inline void add(int x,int v)
{
for(int i=x;i<=n;i+=lowbit(i))
if(tim[i]!=T) c[i]=v,tim[i]=T;
else c[i]+=v;
}
inline int getsum(int x)
{
int sum=0;
for(int i=x;i>=1;i-=lowbit(i))
if(tim[i]==T) sum+=c[i];
return sum;
}
inline void CDQ(int l,int r)
{
if(l==r) return;
int i,j,mid=l+r>>1,l1=l,l2=mid+1;
fo(i,l,r)
if(p[i].a<=mid) tmp[l1++]=p[i];
else tmp[l2++]=p[i];
memcpy(p+l,tmp+l,sizeof(p[0])*(r-l+1));
CDQ(l,mid);T++;j=l;
fo(i,mid+1,r)
{
for(j;j<=mid && p[j].w<p[i].w;j++)
add(p[j].t,1);
res[p[i].t]+=getsum(p[i].t);
}
CDQ(mid+1,r);
l1=l,l2=mid+1;
fo(i,l,r)
{
if((comp(p[l1],p[l2]) || l2>r) && l1<=mid)
tmp[i]=p[l1++];
else
tmp[i]=p[l2++];
}
memcpy(p+l,tmp+l,sizeof(p[0])*(r-l+1));
}
int main()
{
int i,j,c;
scanf("%d%d",&n,&m);
for(i=n;i>=1;i--)
scanf("%d",&p[i].a),p[i].w=i,to[p[i].a]=i;
for(i=m;i>=1;i--)
{
scanf("%d",&c);
p[to[c]].t=i-m+n;
}
fo(i,1,n) if(!p[i].t) p[i].t=++num;
sort(p+1,p+n+1,comp);
CDQ(1,n);
fo(i,1,n) p[i].w=n-p[i].w+1,p[i].a=n-p[i].a+1;
sort(p+1,p+n+1,comp);
CDQ(1,n);
fo(i,1,n) res[i]+=res[i-1];
for(i=n;i>=n-m+1;i--) printf("%lld\n",res[i]);
return 0;
}