交换位置L,R,对答案产生的影响是L,R内(比L大的数个数-比L小的数个数)+(比R小的数个数-比R大的数的个数)+(L和R交换后应该+1或-1)。求这个东西用树套树就可以(做数据结构做傻了,还有很多其他优秀的做法)。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 1700005
using namespace std;
void read(int &a)
{
a=0;char c=getchar();
while(c<'0'||c>'9')
c=getchar();
while(c>='0'&&c<='9')
{
a*=10;a+=c-'0';
c=getchar();
}
}
int a[20005];
int LSH[20005];
struct xds{
int l,r;
int rt;
}tree[400005];
int n,m;
int val[maxn],sz[maxn];
int ch[maxn][2],fa[maxn];
int cnt[maxn],tot,D;
bool dir(int x)
{return x==ch[fa[x]][1];}
void up(int x)
{
sz[x]=cnt[x];
if(ch[x][0])sz[x]+=sz[ch[x][0]];
if(ch[x][1])sz[x]+=sz[ch[x][1]];
}
void rotate(int x)
{
int y=fa[x],z=fa[y];
bool b=dir(x);
int a=ch[x][!b];
if(z) ch[z][dir(y)]=x;
else tree[D].rt=x;
fa[x]=z;ch[x][!b]=y;
fa[y]=x;ch[y][b]=a;
if(a) fa[a]=y;
up(y);up(x);
}
void splay(int x,int e)
{
while(fa[x]!=e)
{
int y=fa[x];
if(fa[y]==e) rotate(x);
else
{
bool b=dir(x),c=dir(y);
if(b^c) {rotate(y);rotate(x);}
else {rotate(x);rotate(x);}
}
}
}
int nxt,t1;
int pre,t2;
void find_nxt(int p,int x)
{
for(;p;p=ch[p][val[p]<=x])
{
if(val[p]>x&&val[p]<nxt)
nxt=val[p],t1=p;
}
}
void find_pre(int p,int x)
{
for(;p;p=ch[p][val[p]<x])
{
if(val[p]<x&&val[p]>pre)
pre=val[p],t2=p;
}
}
void insert(int f,int &x,int k)
{
if(!x)
{
x=++tot;
cnt[x]=sz[x]=1;
val[x]=k;fa[x]=f;
splay(x,0);
return ;
}
if(val[x]==k)
{
cnt[x]++;sz[x]++;
splay(x,0);
return ;
}
sz[x]++;
insert(x,ch[x][val[x]<k],k);
}
void find(int x,int d)
{
for(int i=x;i;i=ch[i][val[i]<d])
if(val[i]==d){splay(i,0);return ;}
}
void del(int x,int d)
{
find(x,d);
if(cnt[tree[D].rt]>1)
{
cnt[tree[D].rt]--;
sz[tree[D].rt]--;
return ;
}
pre=-1;
find_pre(tree[D].rt,d);
splay(t2,tree[D].rt);
int C=ch[tree[D].rt][1];
ch[t2][1]=C;fa[C]=t2;
fa[t2]=0;tree[D].rt=t2;
up(t2);
}
int pos;
void change(int x,int d)
{
if(tree[x].l<=pos&&tree[x].r>=pos)
{
D=x;del(tree[x].rt,a[pos]);
insert(0,tree[x].rt,d);
if(tree[x].l==tree[x].r) return ;
}
int mid=(tree[x].l+tree[x].r)>>1;
if(mid>=pos)change(x<<1,d);
else change(x<<1|1,d);
}
void build(int x,int l,int r)
{
tree[x].l=l;
tree[x].r=r;D=x;
for(int i=l;i<=r;i++)
insert(0,tree[x].rt,a[i]);
insert(0,tree[x].rt,n+1);
insert(0,tree[x].rt,0);
if(l==r) return ;
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
}
int L,R,p1;
int ask(int x)
{
if(tree[x].l>=L&&tree[x].r<=R)
{
D=x;nxt=n+2;
find_nxt(tree[x].rt,p1);
splay(t1,0);
int ans=sz[t1]-sz[ch[t1][0]]-1;
pre=-1;
find_pre(tree[x].rt,p1);
splay(t2,0);
ans-=sz[t2]-sz[ch[t2][1]]-1;
return ans;
}
int mid=(tree[x].l+tree[x].r)>>1;
int ans=0;
if(mid>=L) ans+=ask(x<<1);
if(mid<R) ans+=ask(x<<1|1);
return ans;
}
int S[20005],top;
int ANS;
struct Tree_arr{
int c[20005];
int ask_arr(int x)
{
int ans=0;
while(x>=1)
{ans+=c[x];x-=x&(-x);}
return ans;
}
void change(int x)
{
while(x<=n)
{c[x]+=1;x+=x&(-x);}
}
void insert_arr()
{
for(int i=1;i<=top;i++)
ANS+=ask_arr(S[i]);
while(top) change(S[top--]);
}
}Arr;
bool cmp(int A,int B)
{return a[A]>a[B];}
void Lsh()
{
sort(LSH+1,LSH+n+1);
int len=unique(LSH+1,LSH+n+1)-LSH-1;
for(int i=1;i<=n;i++)
a[i]=lower_bound(LSH+1,LSH+len+1,a[i])-LSH;
for(int i=1;i<=n;i++) LSH[i]=i;
sort(LSH+1,LSH+n+1,cmp);
int p=1;
while(p<=n)
{
S[++top]=LSH[p++];
while(a[LSH[p]]==a[LSH[p-1]])
S[++top]=LSH[p++];
Arr.insert_arr();
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{read(a[i]);LSH[i]=a[i];}
Lsh();
printf("%d\n",ANS);
build(1,1,n);
scanf("%d",&m);
int x,y;
for(int i=1;i<=m;i++)
{
read(x);read(y);
if(x>y) swap(x,y);
L=x+1,R=y-1;p1=a[x];
int Add=ask(1);
p1=a[y];
Add-=ask(1);
ANS+=Add;
if(a[x]>a[y]) ANS--;
if(a[x]<a[y]) ANS++;
printf("%d\n",ANS);
pos=x;change(1,a[y]);
pos=y;change(1,a[x]);
swap(a[x],a[y]);
}
return 0;
}