# Johnny and New Toy

Johnny has a new toy. As you may guess, it is a little bit extraordinary. The toy is a permutation $P$ of numbers from $1$ to $n$, written in one row next to each other.

For each $i$ from $1$ to $n - 1$ between $P_i$ and $P_{i + 1}$ there is a weight $W_i$ written, and those weights form a permutation of numbers from $1$ to $n - 1$. There are also extra weights $W_0 = W_n = 0$.

The instruction defines subsegment $[L, R]$ as good if $W_{L - 1} < W_i$ and $W_R < W_i$ for any $i$ in $\{L, L + 1, \ldots, R - 1\}$. For such subsegment it also defines $W_M$ as minimum of set $\{W_L, W_{L + 1}, \ldots, W_{R - 1}\}$.

Now the fun begins. In one move, the player can choose one of the good subsegments, cut it into $[L, M]$ and $[M + 1, R]$ and swap the two parts. More precisely, before one move the chosen subsegment of our toy looks like:

$W_{L - 1}, P_L, W_L, \ldots, W_{M - 1}, P_M, W_M, P_{M + 1}, W_{M + 1}, \ldots, W_{R - 1}, P_R, W_R$

and afterwards it looks like this:

$W_{L - 1}, P_{M + 1}, W_{M + 1}, \ldots, W_{R - 1}, P_R, W_M, P_L, W_L, \ldots, W_{M - 1}, P_M, W_R$

Such a move can be performed multiple times (possibly zero), and the goal is to achieve the minimum number of inversions in $P$.

Johnny's younger sister Megan thinks that the rules are too complicated, so she wants to test her brother by choosing some pair of indices $X$ and $Y$, and swapping $P_X$ and $P_Y$ ($X$ might be equal $Y$). After each sister's swap, Johnny wonders, what is the minimal number of inversions that he can achieve, starting with current $P$ and making legal moves?

You can assume that the input is generated randomly. $P$ and $W$ were chosen independently and equiprobably over all permutations; also, Megan's requests were chosen independently and equiprobably over all pairs of indices.

$2 \leq n \leq 2 \cdot 10^5,1 \leq q \leq 5 \cdot 10^4$

## Tutorial (en)

Let us start with an analysis of good subsegments for the fixed permutation. The whole permutation is a good subsegment itself, as $W_0 = W_n = 0 < W_k$ for any $k \in [1, 2, \ldots, n - 1]$. If we denote the minimal weight in $W_1, \ldots, W_{n - 1}$ as $W_m$, then we can notice that subsegments $[1, m]$ and $[m + 1, n]$ contain all good subsegments except the whole permutation. As a result, we can recursively find all good subsegments by recursive calls in $[1, m]$ and $[m + 1, n]$. We can view the structure of good subsegments as a binary tree.

Example structure of tree for $P = [3, 4, 6, 2, 1, 5]$ and $W = [5, 2, 3, 1, 4]$:

Now we want to analyze the possible moves for players. It turns out that the player's move is equivalent to choosing a vertex of a tree and swapping its left and right subtree. Notice that moves made in different vertices influence disjoint pairs of elements, so in some sense these moves are independent if we are interested only in the number of inversions. This observation allows us to find a simple method for calculating the result. For each vertex, calculate the number of inversions between the left and right subtree. Using these numbers for each vertex, we can find out whether we want to swap its subtrees or not, so the result can be calculated by a simple loop over all vertices.

From randomness of the input, we can deduce that the tree we built has height $\mathcal{O}(\log n)$. We can calculate the number of inversions easily if in each vertex we keep a structure with elements from permutation contained in that vertex. Such structure must support querying the number of elements smaller than some $x$. The shortest implementation uses the ordered set, but any BST can do it (segment tree needs some squeezing to fit into ML).

The above solution works fast if there are no queries. We can view each request as two removals and additions of elements. If so, we can notice that each query modifies the number of inversions in at most $\mathcal{O}(\log n)$ vertices. So all we need to do is update the number of inversions in these vertices and recalculate the global result.

Building a tree and calculating initial number of inversions takes $\mathcal{O}(n \log n)$ or $\mathcal{O}(n \log^2n)$, answering each query cost $\mathcal{O}(\log^2 n)$, so the final complexity is $\mathcal{O}(n \log n + q \log^2 n)$.

CO int N=2e5+10;
int in[N],weight[N];
int64 ans;

// cartesian tree node
// while creating we calculate set of elements and number of inversions
struct node{
int splitter;
int64 invs;
ordered_set S;
node*left,*right;

node():splitter(0),invs(0),left(0),right(0) {}
}*root;

// add/delete contribution from given node to result
if(cur->splitter==0) return;
ans+=mt*min(cur->invs,(int64)cur->left->S.size()*(int64)cur->right->S.size()-cur->invs); // swaping
}

// Create cartesian tree
// Because expected depth is O(logn) we can use bruteforce to find the smallest weight
node*get_cartesian(int from,int to){
node*ret=new node();
if(from==to){
ret->S.insert(in[from]);
return ret;
}
int id=from;
for(int i=from+1;i<to;++i)if(weight[i]<weight[id]) id=i;
ret->splitter=id;
ret->left=get_cartesian(from,id);
ret->right=get_cartesian(id+1,to);
// get elements from ordered set
ret->S=ret->right->S;
for(int v:ret->left->S){
ret->S.insert(v);
ret->invs+=ret->right->S.order_of_key(v);
}
// add contribution to the result
return ret;
}

// depending on mt, removes/add element val on position p
void update_cart(int p,int val,int mt){
node*cur=root;
while(cur->splitter){
if(mt==-1) cur->S.erase(val);
else cur->S.insert(val);
if(p<=cur->splitter){
cur->invs+=mt*cur->right->S.order_of_key(val);
cur=cur->left;
}
else{
cur->invs+=mt*(cur->left->S.size()-cur->left->S.order_of_key(val));
cur=cur->right;
}
}
if(mt==-1) cur->S.erase(val);
else cur->S.insert(val);
cur=root;
while(cur->splitter){
if(p<=cur->splitter) cur=cur->left;
else cur=cur->right;
}
}

int main(){
root=get_cartesian(1,n);
if(x==y) continue;
// remove both numbers
update_cart(x,in[x],-1);
update_cart(y,in[y],-1);
swap(in[x],in[y]);
update_cart(x,in[x],1);
update_cart(y,in[y],1);
}
return 0;
}


# Tree Rotations

$1 \leq n \leq 200000$

## 分析

• 如果我们交换了左右子树，跨越子树的逆序对数量为没交换时左子树中<mid的数的数量*右子树中>=mid的数的数量

• 如果我们没有交换左右子树，那么逆序对数量就是左子树中>=mid的数的数量*右子树中<mid的数的数量

const int MAXT=2e5*20;
int n;
int a[MAXT]; // edit 1
int r,ls[MAXT],rs[MAXT],idx;

void init(int&x)
{
x=++idx;
if(a[x])
return;
init(ls[x]);
init(rs[x]);
}

ll ans1,ans2,ans;

int root[MAXT],sz;
struct PreSegTree
{
int L[MAXT],R[MAXT];
int sum[MAXT];

void pushup(int now)
{
sum[now]=sum[L[now]]+sum[R[now]];
}

void insert(int&now,int l,int r,int p)
{
if(!now)
now=++sz;
if(l==r)
{
sum[now]=1;
return;
}
int mid=(l+r)>>1;
if(p<=mid)
insert(L[now],l,mid,p);
else
insert(R[now],mid+1,r,p);
pushup(now);
}

int merge(int x,int y)
{
if(!x||!y)
return x+y;
ans1+=(ll)sum[R[x]]*sum[L[y]];
ans2+=(ll)sum[L[x]]*sum[R[y]];
L[x]=merge(L[x],L[y]);
R[x]=merge(R[x],R[y]);
pushup(x);
return x;
}
}T;

void solve(int x)
{
if(a[x])
return;
solve(ls[x]);
solve(rs[x]);
ans1=ans2=0;
root[x]=T.merge(root[ls[x]],root[rs[x]]);
ans+=min(ans1,ans2);
}

int main()
{
init(r);
for(int i=1;i<=idx;++i)
if(a[i])
T.insert(root[i],1,n,a[i]);
solve(r);
printf("%lld\n",ans);
return 0;
}


# Minimax

$C$ 有一棵 $n$ 个结点的有根树，根是 $1$ 号结点，且每个结点最多有两个子结点。

1. $x$ 没有子结点，那么它的权值会在输入里给出，保证这类点中每个结点的权值互不相同

2. $x$ 有子结点，那么它的权值有 $p_x$ 的概率是它的子结点的权值的最大值，有 $1-p_x$ 的概率是它的子结点的权值的最小值。

$\sum_{i=1}^{m}i\cdot V_i\cdot D_i^2$

## 题解

https://www.luogu.com.cn/blog/Isaunoya/solution-p5298

$l = \text{ch}[i][0] , r = \text{ch}[i][1]$ 即左儿子右儿子

$m$ 为叶子结点的个数

$f_{i,j} = f_{l,j} * (p_i \sum_{k=1}^{j-1}f_{r,k} + (1-p_i)\sum_{k=j+1}^{m}f_{r,k}) + f_{r,j} * (p_i \sum_{k=1}^{j-1}f_{l,k} + (1-p_i)\sum_{k=j+1}^{m}f_{l,k})$

CO int N=3e5+10;
int fa[N],ch[N][2],cnt[N];
int val[N];
vector<int> all;

int root[N],tot;
int lc[N*20],rc[N*20],sum[N*20],tag[N*20];
int prob[N];

#define mid ((l+r)>>1)
IN void push_up(int x){
}
IN void put_tag(int x,int v){
sum[x]=mul(sum[x],v),tag[x]=mul(tag[x],v);
}
IN void push_down(int x){
if(tag[x]!=1){
if(lc[x]) put_tag(lc[x],tag[x]);
if(rc[x]) put_tag(rc[x],tag[x]);
tag[x]=1;
}
}
void insert(int&x,int l,int r,int p,int v){
x=++tot,sum[x]=v,tag[x]=1;
if(l==r) return;
if(p<=mid) insert(lc[x],l,mid,p,v);
else insert(rc[x],mid+1,r,p,v);
}
int merge(int x,int y,int l,int r,int tx,int ty,CO int v){
if(!x and !y) return 0;
if(!x) {put_tag(y,ty); return y;}
if(!y) {put_tag(x,tx); return x;}
push_down(x),push_down(y);
int slcx=sum[lc[x]],srcx=sum[rc[x]],slcy=sum[lc[y]],srcy=sum[rc[y]]; // edit 1
push_up(x);
return x;
}
void clear(int x,int l,int r){
if(!x) return;
if(l==r) {prob[l]=sum[x]; return;}
push_down(x);
clear(lc[x],l,mid);
clear(rc[x],mid+1,r);
}
#undef mid

void dfs(int x){
if(cnt[x]==0){
insert(root[x],1,all.size(),val[x],1);
}
else if(cnt[x]==1){
dfs(ch[x][0]);
root[x]=root[ch[x][0]];
}
else{
dfs(ch[x][0]),dfs(ch[x][1]);
root[x]=merge(root[ch[x][0]],root[ch[x][1]],1,all.size(),0,0,val[x]);
}
}
int main(){
for(int i=1;i<=n;++i)
for(int i=1;i<=n;++i){
if(cnt[i]) val[i]=mul(val[i],i10000);
else all.push_back(val[i]);
}
sort(all.begin(),all.end());
for(int i=1;i<=n;++i)if(cnt[i]==0)
val[i]=lower_bound(all.begin(),all.end(),val[i])-all.begin()+1;
dfs(1);
clear(root[1],1,all.size());
int ans=0;
for(int i=1;i<=(int)all.size();++i)