1. 程式人生 > >Record of coding:Codeforces 1093E

Record of coding:Codeforces 1093E

E. Intersection of Permutations

You are given two permutations a and b, both consisting of n elements. Permutation of nn elements is such a integer sequence that each value from 1 to n appears exactly once in it.

You are asked to perform two types of queries with them:

1 la ra lb rb">1 la ra lb rb — calculate the number of values which appear in both segment [la;ra] of positions in permutation aa and segment [lb;rb] of positions in permutation b;
  • 2 x y
     — swap values on positions x and y in permutation b.
  • Print the answer for each query of the first type.

    It is guaranteed that there will be at least one query of the first type in the input.

    https://codeforces.com/contest/1093/problem/E Obviously we can use renumeration to make A fixed, and the answer won't be changed.  Firstly,let's consider a weak solution.If we use a 2D-BIT to solve this problem, we find the answer is just the sum on rectangle. To explain this more intuitively,I use f[i][j] to stand for the sum of number less than or equals to j among the first i numbers of the permutation B. Then answer for la,ra,lb and rb equals to  f[ra][rb]-f[la-1][rb]-f[ra][lb-1]+f[la-1][lb-1].This is a simple usage of the principle of inclusion-exclusion. In this weak solution, the complexity of time is O((m+n)(logn)^2), but the complexity of memory come up to O(N^2). Considered of the memory limit of 512MB , this solution is completely unacceptable. So we must compress the usage of memory. My solution is to change each node of the BIT from a BIT into a rb_tree, which consists of all the number fell into this node. This action doesn't change the complexity of time but reduce the memory to O(NlogN). So this problem is solved. Code:
    /*
    ************************************************************************************* * This code is written by akonoh. * * It can only be compiled by c++17 due to the usage of bits/extc++.h * * I used pb_ds to reduce the length of my code * * ************************************************************************************/ #include <bits/stdc++.h> #include <bits/extc++.h> using namespace std; using namespace __gnu_pbds; #define N 200*1000 int n,m; tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> tr[N+7],sb; inline int lb(int x){return x&-x;} void addup(int x,int y) { for(int i = x; i <= n ; i += lb(i)) { tr[i].insert(y); } } void del(int x, int y) { for(int i = x; i <= n; i += lb(i)) { tr[i].erase(y); } } int getans(int x, int y) { int ans = 0; for(int i = x; i > 0; i -= lb(i)) { int p = tr[i].order_of_key(y); if(*tr[i].lower_bound(y)==y)p++; ans += p; //this part is to find how many numbers are smaller or equal to y. } return ans; } int a[N+8],b[N+8]; int main() { scanf("%d%d",&n,&m); for(int i = 1 ; i<= n; i ++) { int x; scanf("%d",&x); a[x]=i; } for(int i = 1; i <= n ;i ++) { int x; scanf("%d",&x); b[i]=a[x];//renumeration } for(int i = 1; i <= n; i ++) addup(i,b[i]); for(int i = 1; i <= m; i ++) { int t; scanf("%d",&t); if(t==1) { int la,ra,lb,rb,ans=0; scanf("%d%d%d%d",&la,&ra,&lb,&rb); ans +=getans(rb,ra); ans -=getans(lb-1,ra); ans -=getans(rb,la-1); ans +=getans(lb-1,la-1); printf("%d\n",ans); } else { int x,y; scanf("%d%d",&x,&y); del(x,b[x]); del(y,b[y]); swap(b[x],b[y]); addup(x,b[x]); addup(y,b[y]); } } }