题目:http://www.luogu.org/problem/show?pid=2448
分析:首先离散化,然后树状数组求所有操作过的数产生的逆序对,再求每个操作过的数与没操作过的数产生的逆序对,因为原始序列有序,所以很方便。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
const int Tmax=200005;
struct node{
int x,p,lisan;
};
node G[Tmax];
int k,last,C1[Tmax],C2[Tmax];
long long int ans;
map<int,int> F,fx;
bool cmp(node lhs,node rhs)
{
return lhs.x<rhs.x;
}
bool cmp2(node lhs,node rhs)
{
return lhs.p<rhs.p;
}
void init()
{
int i;
sort(G+1,G+1+last,cmp);
for(i=1;i<=last;i++)
{
G[i].lisan=i;
fx[G[i].x]=i;
}
sort(G+1,G+1+last,cmp2);
return;
}
int lowbit(int x)
{
return x&-x;
}
int sum(int x)
{
int sum=0;
for(;x>0;x-=lowbit(x))
sum+=C1[x];
return sum;
}
void add(int x)
{
for(;x<=Tmax-1;x+=lowbit(x))
C1[x]++;
return;
}
void work()
{
int i,num;
for(i=1;i<=last;i++)
{
num=sum(Tmax-1)-sum(G[i].lisan);
add(G[i].lisan);
ans+=num;
if(G[i].p>G[i].x)
{
num=fx[G[i].p]-fx[G[i].x]-1;
ans+=max(0,G[i].p-G[i].x-1-num);
}
else {
num=fx[G[i].x]-fx[G[i].p]-1;
ans+=max(0,G[i].x-G[i].p-1-num);
}
}
cout<<ans;
return;
}
int main()
{
int i,a,b,pa,pb;
scanf("%d",&k);
for(i=1;i<=k;i++)
{
scanf("%d%d",&a,&b);
if(!F.count(a)){
pa=++last;
G[pa].x=G[pa].p=a;
F[a]=pa;
}
else pa=F[a];
if(!F.count(b)){
pb=++last;
G[pb].x=G[pb].p=b;
F[b]=pb;
}
else pb=F[b];
swap(G[pa].x,G[pb].x);
}
init();
work();
return 0;
}