[Original question]
3295: [cqoi2011] dynamic reverse order of time limit: 10 sec memory limit: 128 MB
Submit: 778 solved: 263
[Submit] [Status] Description for sequence a, its reverse logarithm is defined as satisfying
I<
JAnd
I>
JNumber pair (
I,
J. 1
NIn a certain order.
MElement. Your task is to count the reverse logarithm of the entire sequence before each element is deleted. The first line of input contains two integers.
NAnd
MThat is, the number of initial elements and the number of deleted elements. Below
NEach row contains one to one
NA positive integer between them, that is, the initial arrangement. Below
MEach row has a positive integer, which is the elements deleted each time. Output contains
MThe number of reverse-order pairs before each element is deleted. Sample input5 4
1
5
3
4
2
5
1
4
2
Sample output5
2
2
1
Example
(, 2) random (,) random (, 2) random (3) random (3 ).
Hint
N <= 100000 m <= 50000
[Digress] I have been thinking about this question. So tired! The idea at the beginning is to add one by one, set a tree array, and then search for it with the Balance Tree each time. Obviously, now I only use splay, and the code is long and efficient. Today, I am reading the blog of hzwer with Syf. In addition, the speech of Uncle Zhe is broken, and the tree structure of the Chairman tree is used.
[Main idea] first use a tree array/merge sort/merge tree (Tears of the time) to find the number of reverse pairs in the total sequence. The position (1 -- X-1 or x + 1 -- N) is maintained with a tree array each time it is deleted, and the weight information is maintained with the weight line tree.
[Detailed algorithm]
① When calculating the total number of Reverse Order pairs, we can calculate the front [I] And back [I], this indicates that the number of front [I] is greater than that of front [I] Before vertex I, and the number of back [I] is smaller than that of front [I.
② At the beginning, the Chairman tree was empty. Therefore, we need to convert it. what we originally calculated is that after a certain number is deleted, the number of reverse pairs in the remaining series will be reduced (that is, the contribution to the remaining series ); now let's change it to: How much contribution will be made to some nodes already inserted in the Chair tree after a certain number is deleted. After calculation, use front or back to subtract it.
For example. For example, if there are columns 5, 4, 3, 2, 1, 4 and 1 have been deleted, and the ANS value is 3. Now we have to delete 3. In the chair tree, the added nodes are 5 and 2. After calculation, 5, 3, and 2 generate a reverse order pair before 3, and a reverse order pair after 3. Front [3] = 2, back [3] = 2, then we can know that ans need to subtract front [3]-1 and back [3]-1, that is, there is only 1 left in ans.
③ How did I implement the subsequent tree array? For exampleComputing or updateL ~ In the Chairman tree within the r rangeOne or someThe number of weights. We can convertComputing or update1 L-1 and 1 -- r prefix, then subtract. The prefix can be solved using a tree array.
[Code]
#include<cstdio>#include<cstring>#define N 100005#define L(x) (x&-x)using namespace std;typedef long long LL;LL ans;struct arr{int l,r;LL sum;}a[6000000];int front[N],back[N],c[N],root[N],pos[N],data[N],A[31],B[31];int n,node,del,x,m,i;inline int ask(int x){int s=0;for (;x;x-=L(x)) s+=c[x];return s;}inline void up(int x){for (;x<=n;x+=L(x)) c[x]++;}inline LL ask_more(int l,int r,int num){ if (l>r) return 0;l--;A[0]=B[0]=0; for (int i=l;i;i-=L(i)) A[++A[0]]=root[i]; for (int i=r;i;i-=L(i)) B[++B[0]]=root[i]; l=1;r=n;LL sum=0; while (l!=r) { int mid=(l+r)>>1; if (num<=mid) { for (int i=1;i<=B[0];i++) sum+=a[a[B[i]].r].sum; for (int i=1;i<=A[0];i++) sum-=a[a[A[i]].r].sum; for (int i=1;i<=B[0];i++) B[i]=a[B[i]].l; for (int i=1;i<=A[0];i++) A[i]=a[A[i]].l; r=mid; } else { for (int i=1;i<=B[0];i++) B[i]=a[B[i]].r; for (int i=1;i<=A[0];i++) A[i]=a[A[i]].r; l=mid+1; } } return sum;}inline LL ask_less(int l,int r,int num){ if (l>r) return 0;l--;A[0]=B[0]=0; for (int i=l;i;i-=L(i)) A[++A[0]]=root[i]; for (int i=r;i;i-=L(i)) B[++B[0]]=root[i]; l=1;r=n;LL sum=0; while (l!=r) { int mid=(l+r)>>1; if (num>mid) { for (int i=1;i<=B[0];i++) sum+=a[a[B[i]].l].sum; for (int i=1;i<=A[0];i++) sum-=a[a[A[i]].l].sum; for (int i=1;i<=B[0];i++) B[i]=a[B[i]].r; for (int i=1;i<=A[0];i++) A[i]=a[A[i]].r; l=mid+1; } else { for (int i=1;i<=B[0];i++) B[i]=a[B[i]].l; for (int i=1;i<=A[0];i++) A[i]=a[A[i]].l; r=mid; } } return sum;}inline void update(int &k,int l,int r){ if (!k) k=++node;a[k].sum++; if (l==r) return; int mid=(l+r)>>1; if (del<=mid) update(a[k].l,l,mid); else update(a[k].r,mid+1,r);}inline int Read(){ char ch=getchar();for (;ch<'0'||ch>'9';ch=getchar()); int x=0;for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; return x;}int main(){ n=Read();m=Read(); for (i=1;i<=n;i++) { data[i]=Read();pos[data[i]]=i; ans+=(front[i]=i-1-ask(data[i]));up(data[i]); } memset(c,0,sizeof(c)); for (i=n;i;i--) back[i]=ask(data[i]-1),up(data[i]); for (i=1;i<m;i++) { printf("%lld\n",ans); del=Read();x=pos[del]; ans-=front[x]-ask_more(1,x-1,del); ans-=back[x]-ask_less(x+1,n,del); for (;x<=n;x+=L(x)) update(root[x],1,n); } printf("%lld\n",ans); return 0;}