BZOJ3295 动态逆序对(树状数组套线段树)

[Cqoi2011]动态逆序对

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 6058  Solved: 2117
[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

 

题解:

   普通的树状数组,无法记录位置,不能知道一次之后记录的是所以位置的信息,

   一次删除的时候,不能知道哪些值是比它小的,因为位置的影响,

   所以需要树套树,在开一层位置,这样就可以了,动态开点,n logn log n的空间复杂度。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 
 7 #define N 100007
 8 #define M 10000007
 9 using namespace std;
10 int n,m,cnt;
11 int a[N],id[N],bit[N],lson[M],rson[M],tree[M];
12 long long ans;
13 
14 int lowbit(int x){return x&-x;}
15 void addy(int &u,int l,int r,int x,int y)
16 {
17     if(!u)u=++cnt;
18     if(l==r){tree[u]+=y;return;}
19     int mid=(l+r)>>1;
20     if(x<=mid) addy(lson[u],l,mid,x,y);
21     else addy(rson[u],mid+1,r,x,y);
22     tree[u]=tree[lson[u]]+tree[rson[u]];
23 }
24 void addx(int x,int y,int val)
25 {
26     for (int i=x;i<=n;i+=lowbit(i))
27         addy(i,1,n,y,val);
28 }
29 int queryy(int u,int l,int r,int i,int j)
30 {
31     if(!u) return 0;
32     if(l==i&&r==j) return tree[u];
33     int mid=(l+r)>>1;
34     if(j<=mid) return queryy(lson[u],l,mid,i,j);
35     else if(i>mid) return queryy(rson[u],mid+1,r,i,j);
36     return queryy(lson[u],l,mid,i,mid)+queryy(rson[u],mid+1,r,mid+1,j);
37 }
38 int queryx(int x,int l,int r)
39 {
40     int ans=0;
41     for (int i=x;i>=1;i-=lowbit(i))
42         ans+=queryy(i,1,n,l,r);
43     return ans;
44 }
45 int main()
46 {
47     scanf("%d%d",&n,&m),cnt=n;
48     for(int i=1;i<=n;i++)
49     {
50         scanf("%d",&a[i]);
51         ans+=(long long)queryx(i-1,a[i]+1,n);
52         id[a[i]]=i;
53         addx(i,a[i],1);
54     }
55     while(m--)
56     {
57         printf("%lld\n",ans);
58         int x;scanf("%d",&x);
59         ans-=(long long)queryx(id[x]-1,x+1,n);
60         ans-=(long long)queryx(n,1,x-1);
61         ans+=(long long)queryx(id[x]-1,1,x-1);
62         addx(id[x],x,-1);
63     }
64 }

 

posted @ 2017-12-27 09:15  Kaiser-  阅读(238)  评论(0编辑  收藏  举报