bzoj 3295 [Cqoi2011]动态逆序对

来源:互联网 发布:php 源代码 保护 编辑:程序博客网 时间:2024/06/05 07:42

3295: [Cqoi2011]动态逆序对

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 4785  Solved: 1613
[Submit][Status][Discuss]

Description

对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

Input

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

Output

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

Sample Input

5 4
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)。

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;}


原创粉丝点击