Problem:
Score : 1000 points

Problem Statement

You are given an integer sequence of length N: A_1,A_2,...,A_N. Let us perform Q operations in order.
The i-th operation is described by two integers X_i and Y_i. In this operation, we will choose one of the following two actions and perform it:

Swap the values of A_{X_i} and A_{Y_i}

Do nothing

There are 2^Q ways to perform these operations. Find the sum of the inversion numbers of the final sequences for all of these ways to perform operations, modulo 10^9+7.

Here, the inversion number of a sequence P_1,P_2,...,P_M is the number of pairs of integers (i,j) such that 1\leq i < j\leq M and P_i > P_j.

Constraints

1 \leq N \leq 3000

0 \leq Q \leq 3000

0 \leq A_i \leq 10^9(1\leq i\leq N)

1 \leq X_i,Y_i \leq N(1\leq i\leq Q)

X_i\neq Y_i(1\leq i\leq Q)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N Q
A_1
:
A_N
X_1 Y_1
:
X_Q Y_Q

Output

Print the sum of the inversion numbers of the final sequences, modulo 10^9+7.

Sample Input 1

3 2
1
2
3
1 2
1 3

Sample Output 1

6

There are four ways to perform operations, as follows:

Do nothing, both in the first and second operations. The final sequence would be 1,2,3, with the inversion number of 0.

Do nothing in the first operation, then perform the swap in the second. The final sequence would be 3,2,1, with the inversion number of 3.

Perform the swap in the first operation, then do nothing in the second. The final sequence would be 2,1,3, with the inversion number of 1.

Perform the swap, both in the first and second operations. The final sequence would be 3,1,2, with the inversion number of 2.

The sum of these inversion numbers, 0+3+1+2=6, should be printed.

Sample Input 2

5 3
3
2
3
1
4
1 5
2 3
4 2

Sample Output 2

36

Sample Input 3

9 5
3
1
4
1
5
9
2
6
5
3 5
8 9
7 9
3 2
3 8

Sample Output 3

425

Solution in C++14 (Clang 3.8.0) (judge verdict: Time Limit Exceeded)

#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <functional>
#include <iomanip>
#define vll vector<ll>
#define vvvl vector<vvl>
#define vvl vector<vector<ll>>
#define VV(a, b, c, d) vector<vector<d> >(a, vector<d>(b, c))
#define VVV(a, b, c, d) vector<vvl>(a, vvl(b, vll (c, d)));
#define re(c, b) for(ll c=0;c<b;c++)
#define all(obj) (obj).begin(), (obj).end()
typedef long long int ll;
typedef long double ld;
using namespace std;

ll P = 1000000007;
ll I = 500000004;
struct LazySegmentTree {
private:
    int n;
    vector<ll> node, lazy;

public:
    LazySegmentTree(vector<ll> v) {
        int sz = (int)v.size();
        n = 1; while(n < sz) n *= 2;
        node.resize(2*n-1);
        lazy.resize(2*n-1, 1);
        for(int i=0; i<sz; i++) node[i+n-1] = v[i];
        for(int i=n-2; i>=0; i--) node[i] = node[i*2+1] + node[i*2+2];
    }

    void eval(int k, int l, int r) {
        if(lazy[k] != 1) {
            node[k] = (node[k] * lazy[k])%P;
            if(r - l > 1) {
                lazy[2*k+1] = (lazy[2*k+1]*lazy[k])%P;
                lazy[2*k+2] = (lazy[2*k+2]*lazy[k])%P;
            }
            lazy[k] = 1;
        }
    }

    void add(int a, int b, ll x, int k=0, int l=0, int r=-1) {
        if(r < 0) r = n;
        eval(k, l, r);
        if(b <= l || r <= a) return;

        if(a <= l && r <= b) {
            lazy[k] = (lazy[k]*x)%P;
            eval(k, l, r);
        }
        else {
            add(a, b, x, 2*k+1, l, (l+r)/2);
            add(a, b, x, 2*k+2, (l+r)/2, r);
            node[k] = (node[2*k+1]+node[2*k+2])%P;
        }
    }

    void adx(int a, int b, ll x, int k=0, int l=0, int r=-1) {
        if(r < 0) r = n;
        eval(k, l, r);
        if(b <= l || r <= a) return;
        if(a <= l && r <= b) {
            eval(k, l, r);
        }else {
            node[k] = (node[k]+x)%P;
        }
    }

    ll getsum(int a, int b, int k=0, int l=0, int r=-1) {
        if(r < 0) r = n;
        eval(k, l, r);
        if(b <= l || r <= a) return 0;
        if(a <= l && r <= b) return node[k];
        ll vl = getsum(a, b, 2*k+1, l, (l+r)/2);
        ll vr = getsum(a, b, 2*k+2, (l+r)/2, r);
        return (vl + vr)%P;
    }
};


int main(int argc, char const *argv[]) {
  ll n, q;std::cin >> n >> q;
  vll a(n);re(i, n) scanf("%lld", &a[i]);

  vvl query = VV(q, 2, 0, ll);
  re(i, q) {
    scanf("%lld %lld", &query[i][0], &query[i][1]);
    query[i][0]--, query[i][1]--;
  }
  reverse(all(query));
  LazySegmentTree dp(vector<ll>(10000001, 1));
  LazySegmentTree rev(vector<ll>(10000001, 0));

  for(auto v:query){
    vvl tmp;//i, j, flip or not, num
    ll x = min(v[0], v[1]), y = max(v[0], v[1]);
    // x, y
    ll adr = x*3000+y;
    tmp.push_back(vll{x, y, 1, dp.getsum(adr, adr+1)});
    tmp.push_back(vll{x, y, 0, rev.getsum(adr, adr+1)});
    for(int i=0;i<n;i++){
      if(i==x||i==y) continue;
      if(i<x){
        adr = i*3000+y;
        tmp.push_back(vll{i, x, 1, rev.getsum(adr, adr+1)});
        tmp.push_back(vll{i, x, 0, dp.getsum(adr, adr+1)});
      }else if(y<i){
        adr = y*3000+i;
        tmp.push_back(vll{x, i, 1, rev.getsum(adr, adr+1)});
        tmp.push_back(vll{x, i, 0, dp.getsum(adr, adr+1)});
      }else{
        adr = i*3000+y;
        tmp.push_back(vll{x, i, 1, rev.getsum(adr, adr+1)});
        tmp.push_back(vll{x, i, 0, dp.getsum(adr, adr+1)});
      }
    }
    for(int i=0;i<n;i++){
      if(i==x||i==y) continue;
      if(y<i){
        adr = x*3000+i;
        tmp.push_back(vll{y, i, 1, rev.getsum(adr, adr+1)});
        tmp.push_back(vll{y, i, 0, dp.getsum(adr, adr+1)});
      }else if(i<x){
        adr = i*3000+x;
        tmp.push_back(vll{i, y, 1, rev.getsum(adr, adr+1)});
        tmp.push_back(vll{i, y, 0, dp.getsum(adr, adr+1)});
      }else{
        adr = x*3000+i;
        tmp.push_back(vll{i, y, 1, rev.getsum(adr, adr+1)});
        tmp.push_back(vll{i, y, 0, dp.getsum(adr, adr+1)});
      }
    }
    for(auto ad:tmp){
      ll adr = ad[0]*3000+ad[1];
      if(ad[2]==1) rev.adx(adr, adr+1, ad[3]);
      else dp.adx(adr, adr+1, ad[3]);
    }
    //関係ないものは2倍
    //xかyに関係するものはinv[2]を掛けておく
    for(int i=0;i<n;i++){
      if(i!=x&&i!=y){
        dp.add(i*3000+x, i*3000+x+1, I);
        dp.add(x*3000+i, x*3000+i+1, I);
        rev.add(i*3000+x, i*3000+x+1, I);
        rev.add(x*3000+i, x*3000+i+1, I);
        dp.add(i*3000+y, i*3000+y+1, I);
        dp.add(y*3000+i, y*3000+i+1, I);
        rev.add(i*3000+y, i*3000+y+1, I);
        rev.add(y*3000+i, y*3000+i+1, I);
      }
    }
    dp.add(x*3000+y, x*3000+y+1, I);
    dp.add(y*3000+x, y*3000+x+1, I);
    rev.add(x*3000+y, x*3000+y+1, I);
    rev.add(y*3000+x, y*3000+x+1, I);
    dp.add(0, 10000001, 2);
    rev.add(0, 10000001, 2);

  }
  ll ans = 0;
  for(int i=0;i<n;i++){
    for(int j=i+1;j<n;j++){
      ll adr = i*3000+j;
      if(a[i]<a[j]) ans = (ans + rev.getsum(adr, adr+1))%P;
      if(a[i]>a[j]) ans = (ans + dp.getsum(adr, adr+1))%P;
    }
  }
  std::cout << ans << '\n';
  return 0;
}