codeforces contest 785 problem E(分块)

来源:互联网 发布:jquery ajax get json 编辑:程序博客网 时间:2024/06/08 08:34

Anton and Permutation
time limit per test
4 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

Anton likes permutations, especially he likes to permute their elements. Note that a permutation ofn elements is a sequence of numbers {a1, a2, ..., an}, in which every number from1 to n appears exactly once.

One day Anton got a new permutation and started to play with it. He does the following operationq times: he takes two elements of the permutation and swaps these elements. After each operation he asks his friend Vanya, how many inversions there are in the new permutation. The number of inversions in a permutation is the number of distinct pairs (i, j) such that1 ≤ i < j ≤ n and ai > aj.

Vanya is tired of answering Anton's silly questions. So he asked you to write a program that would answer these questions instead of him.

Initially Anton's permutation was {1, 2, ..., n}, that isai = i for alli such that 1 ≤ i ≤ n.

Input

The first line of the input contains two integers n andq (1 ≤ n ≤ 200 000, 1 ≤ q ≤ 50 000) — the length of the permutation and the number of operations that Anton does.

Each of the following q lines of the input contains two integersli andri(1 ≤ li, ri ≤ n) — the indices of elements that Anton swaps during thei-th operation. Note that indices of elements that Anton swaps during thei-th operation can coincide. Elements in the permutation are numbered starting with one.

Output

Output q lines. The i-th line of the output is the number of inversions in the Anton's permutation after thei-th operation.

Examples
Input
5 44 52 42 52 2
Output
1433
Input
2 12 1
Output
1
Input
6 71 43 52 33 33 62 15 1
Output
567710118
Note

Consider the first sample.

After the first Anton's operation the permutation will be {1, 2, 3, 5, 4}. There is only one inversion in it: (4, 5).

After the second Anton's operation the permutation will be {1, 5, 3, 2, 4}. There are four inversions: (2, 3),(2, 4), (2, 5) and (3, 4).

After the third Anton's operation the permutation will be {1, 4, 3, 2, 5}. There are three inversions: (2, 3),(2, 4) and (3, 4).

After the fourth Anton's operation the permutation doesn't change, so there are still three inversions.


题意:一个1-n的数组,q次询问,每次交换两个数的位置 问每次操作后的逆序数对

解:关键思想就是每次交换这两个数后 对序列的影响 在区间范围之外的不产生影响,区间范围之内的统计比a[l] 和 a[r]小的个数就能算出答案

如果是整块直接二分查找,不是整块暴力枚举

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <bits/stdc++.h>using namespace std;const int N = 300000+10;typedef long long LL;int lx[N], rx[N], a[N], id[N];vector<int>p[N];void init(int n){    for(int i=1; i<=n; i++) a[i]=i;    int k=(int)sqrt(1.0*n),i;    for(i=1; i*k<n; i++)    {        lx[i]=(i-1)*k+1,rx[i]=i*k,p[i].clear();        for(int j=lx[i]; j<=rx[i]; j++) p[i].push_back(a[j]),id[j]=i;    }    lx[i]=(i-1)*k+1,rx[i]=n,p[i].clear();    for(int j=lx[i]; j<=rx[i]; j++) p[i].push_back(a[j]),id[j]=i;    return ;}LL ans;int query(int l,int r,int v){    if(l>r) return 0;    int l1=id[l],r1=id[r],sum=0;    if(l1==r1)    {        for(int i=l;i<=r;i++) if(a[i]<v) sum++;        return sum;    }    else    {        for(int i=l;i<=rx[l1];i++) if(a[i]<v) sum++;        for(int i=lx[r1];i<=r;i++) if(a[i]<v) sum++;        for(int i=l1+1;i<r1;i++) sum+=(lower_bound(p[i].begin(),p[i].end(),v)-p[i].begin());        return sum;    }}void update(int l,int r){    int x=a[l],y=a[r];    int l1=id[l], r1=id[r];    p[l1].erase(lower_bound(p[l1].begin(),p[l1].end(),x));    p[r1].erase(lower_bound(p[r1].begin(),p[r1].end(),y));    p[l1].insert(upper_bound(p[l1].begin(),p[l1].end(),a[r]),a[r]);    p[r1].insert(upper_bound(p[r1].begin(),p[r1].end(),a[l]),a[l]);    swap(a[l],a[r]);    return ;}int main(){    int n, q;    scanf("%d %d", &n, &q);    init(n);    ans=0;    for(int i=0; i<q; i++)    {        int l, r;        scanf("%d %d", &l, &r);        if(l==r)        {            printf("%I64d\n",ans);            continue;        }        if(l>r) swap(l,r);        ans+=(r-l-1-2*query(l+1,r-1,a[l]));        ans-=(r-l-1-2*query(l+1,r-1,a[r]));        if(a[l]<a[r]) ans++;        else ans--;        update(l,r);        printf("%I64d\n",ans);    }    return 0;}









原创粉丝点击