


/*
根右左遍历后最长上升子序列
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
inline LL read()
{
char c=getchar();LL num=0,f=1;
for(;!isdigit(c);c=getchar())
f=c=='-'?-1:f;
for(;isdigit(c);c=getchar())
num=num*10+c-'0';
return num*f;
}
const int N=1e5+5;
int n;
LL w[N];
int son[N][2];
LL dfn[N],tim;
void dfs(int u)
{
dfn[++tim]=w[u];
if(son[u][1]!=0)
dfs(son[u][1]);
if(son[u][0]!=0)
dfs(son[u][0]);
}
LL lis[N],len;
int main()
{
freopen("point.in","r",stdin);
freopen("point.out","w",stdout);
int size = 256 << 20; // 256MB
char *p = (char*)malloc(size) + size;
__asm__("movl %0, %%esp
" :: "r"(p));
n=read();
for(int i=1;i<=n;++i)
w[i]=read();
for(int i=1;i<=n;++i)
son[i][0]=read(),son[i][1]=read();
dfs(1);
lis[len=1]=dfn[1];
for(int i=2;i<=tim;++i)
{
if(dfn[i]>lis[len]) lis[++len]=dfn[i];
else lis[lower_bound(lis+1,lis+len+1,dfn[i])-lis]=dfn[i];
}
cout<<len;
fclose(stdin);fclose(stdout);
return 0;
}


/*
序列分为移动的序列和未移动的序列两部分
询问离散化后
对于移动的序列,抽出来树状数组统计逆序对
对于未移动的序列,想办法能直接统计答案
首先维护哪些数未被移动过,然后对于未被移动过的数求前缀和sum[i]
这样就得到了1~i中未被移动过的数的个数,进而能O(1)得出每段区间未被移动的数的个数。
考虑一个移动了的元素,从i向前移动到了j,那么他对答案的贡献,就是sum[j,i]
因为向前移动后[j,i]这段区间所有数都比他小。
同理一个元素从i向后移动到了j,那么他对答案的贡献为sum[i,j]
所以未被移动的元素对答案的贡献和就是Σabs(sum[原来位置]-sum[移动后的位置])
*/
#include<bits/stdc++.h>
#define N 200007
#define ll long long
using namespace std;
int n,m,cnt,num;
ll ans;
ll pos[N],a[N],sum[N];
struct node{
int L,R;
}ask[N];
struct BIT_{
int n;ll a[N];
static int lowbit(int x){
return x & -x;
}
void clear(){
for(int i=1;i<=n;i++) a[i]=0;
}
ll query(int pos){
ll ans=0;
for(int i=pos;i>0;i-=lowbit(i)) ans+=a[i];
return ans;
}
void update(int pos,int val){
for(int i=pos;i<=n;i+=lowbit(i)) a[i]+=val;
}
}bit;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void discrete()
{
for(int i=1;i<=n;i++)
{
ask[i].L=read();ask[i].R=read();
a[i]=ask[i].L;a[i+n]=ask[i].R;
pos[i]=i;pos[i+n]=i+n;
}
sort(a+1,a+n*2+1);
num=unique(a+1,a+n*2+1)-a-1;
for(int i=1;i<=num;i++) sum[i]=sum[i-1]+a[i]-a[i-1]-1;
for(int i=1;i<=n;i++)
{
ask[i].L=lower_bound(a+1,a+num+1,ask[i].L)-a;
ask[i].R=lower_bound(a+1,a+num+1,ask[i].R)-a;
swap(pos[ask[i].L],pos[ask[i].R]);
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
n=read();discrete();
bit.n=n<<1; bit.clear();
for(int i=num;i>=1;i--)
{
ans+=bit.query(pos[i]);
ans+=abs(sum[pos[i]]-sum[i]);
bit.update(pos[i],1);
}
cout<<ans<<endl;
return 0;
}



#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 200007
using namespace std;
int n,m,ans,cnt;
int head[N],pos[N],vis[N];
struct edge{
int u,v,nxt;
}e[N<<1];
struct node{
int col,x,cur;
};queue<node>q;
inline void add(int u,int v)
{
e[++cnt].v=v;e[cnt].nxt=head[u];head[u]=cnt;
}
inline int read()
{
int x=0,f=1;char c=getchar();
while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void bfs_change(int cur,int change)
{
while(!q.empty()) q.pop();
memset(vis,0,sizeof vis);
node u;u.col=pos[1];u.x=1;vis[1]=1;
q.push(u);
while(!q.empty())
{
u=q.front();q.pop();
if(u.col==cur) pos[u.x]=change;
for(int i=head[u.x];i;i=e[i].nxt)
{
int v=e[i].v;
if(vis[v]) continue;
vis[v]=1;
node tmp;tmp.x=v;tmp.col=pos[v];q.push(tmp);
}
}
}
void bfs_calc()
{
ans=1;
while(!q.empty()) q.pop();
memset(vis,0,sizeof vis);
node u;u.col=pos[1];u.x=1;u.cur=pos[1];
vis[1]=1;q.push(u);
while(!q.empty())
{
u=q.front();q.pop();
if(u.col!=u.cur) ans++;
for(int i=head[u.x];i;i=e[i].nxt)
{
int v=e[i].v;
if(vis[v]) continue;
vis[v]=1;node tmp;
tmp.x=v;tmp.col=pos[v];tmp.cur=pos[u.x];q.push(tmp);
}
}
}
int main()
{
freopen("simulator.in","r",stdin);
freopen("simulator.out","w",stdout);
int x,y;
n=read();m=read();
for(int i=1;i<=n;i++) pos[i]=read();
for(int i=1;i<n;i++)
{
x=read();y=read();
add(x,y);add(y,x);
}
for(int i=1;i<=m;i++)
{
x=read();y=read();
bfs_change(x,y);
bfs_calc();
printf("%d
",ans);
}
return 0;
}
30暴力
/*
bzoj1483 放到树上
见https://www.cnblogs.com/L-Memory/p/9898249.html
同理 vector+启发式合并。
*/
#include<bits/stdc++.h>
#define ll long long
#define M 200010
using namespace std;
int read()
{
int nm = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
return nm * f;
}
int note[M], sz[M], cor[M], id[M];
vector<int>to[M], to1[M];
int n, q, ans;
void dfs(int now, int fa)
{
if(cor[now] != 0 && cor[now] != cor[fa]) ans++;
for(int i = 0; i < to[now].size(); i++)
{
int vj = to[now][i];
if(vj == fa) continue;
dfs(vj, now);
}
}
void del(int x)
{
for(int i = 0; i < to[x].size(); i++)
{
int vj = to[x][i];
if(cor[vj] != cor[x]) ans--;
}
}
void insert(int x)
{
for(int i = 0; i < to[x].size(); i++)
{
int vj = to[x][i];
if(cor[vj] != cor[x]) ans++;
}
}
int tot = 0, tot2 = 0;
int main()
{
freopen("simulator.in", "r", stdin);
freopen("simulator.out", "w", stdout);
n = read(), q = read();
for(int i = 1; i <= n; i++) cor[i] = read(), sz[cor[i]]++, to1[cor[i]].push_back(i), id[i] = i, note[i] = i;
for(int i = 1; i < n; i++)
{
int vi = read(), vj = read();
to[vi].push_back(vj), to[vj].push_back(vi);
}
to[1].push_back(0), cor[0] = 0x3e3e3e3e;
dfs(1, 0);
while(q--)
{
int x = read(), y = read();
int xn = id[x], yn = id[y];
if(sz[xn] < sz[yn])
{
tot += sz[xn], tot2 += to1[xn].size();
for(int i = 0; i < to1[xn].size(); i++)
{
int op = to1[xn][i];
del(op);
to1[yn].push_back(op);
}
for(int i = 0; i < to1[xn].size(); i++)
{
int op = to1[xn][i];
cor[op] = yn;
}
for(int i = 0; i < to1[xn].size(); i++)
{
int op = to1[xn][i];
insert(op);
}
to1[xn].clear();
sz[yn] += sz[xn];
sz[xn] = 0;
id[x] = 0;
}
else
{
tot+=sz[yn], tot2 += to1[yn].size();
for(int i = 0; i < to1[yn].size(); i++)
{
int op = to1[yn][i];
del(op);
to1[xn].push_back(op);
}
for(int i = 0; i < to1[yn].size(); i++)
{
int op = to1[yn][i];
cor[op] = xn;
}
for(int i = 0; i < to1[yn].size(); i++)
{
int op = to1[yn][i];
insert(op);
}
to1[yn].clear();
sz[xn] += sz[yn];
sz[yn] = 0;
id[y] = xn;
id[x] = 0;
}
cout << ans << "
";
}
return 0;
}