P2448 无尽的生命
题目描述
逝者如斯夫,不舍昼夜!
叶良辰认为,他的寿命是无限长的,而且每天都会进步。
叶良辰的生命的第一天,他有1点能力值。第二天,有2点。第n天,就有n点。也就是(S[i]=i)
但是调皮的小A使用时光机,告诉他第x天和第y天,就可以任意交换某两天的能力值。即(S[x]<-->S[y])
小A玩啊玩,终于玩腻了。
叶良辰:小A你给我等着,我有100种办法让你生不如死。除非能在1秒钟之内告知有多少对“异常对”。也就是说,最后的能力值序列,有多少对的两天x,y,其中x<y,但是能力值S[x]>S[y]?
小A:我好怕怕啊。
于是找到了你。
输入输出格式
输入格式:
第一行一个整数k,表示小A玩了多少次时光机
接下来k行,(x_i,y_i),表示将(S[x_i])与(S[y_i])进行交换
输出格式:
有多少“异常对”
输入输出样例
输入样例#1:
2
4 2
1 4
输出样例#1: 复制
4
样例说明
最开始是(1 2 3 4 5 6...)
然后是 (1 4 3 2 5 6...)
然后是 (2 4 3 1 5 6...)
符合的对是([1 4] [2 3] [2 4] [3 4])
数据说明
对于30%的数据,(x_i,y_i <= 2000)
对于70%的数据, (x_i,y_i <= 100000)
对于100%的数据, (x_i.y_i <= 2^31-1 k<=100000)
看来是随机出一道好题
肯定不能用逆序对直接搞
那样做只能得70分?
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define lowbit((a)) (a)&(-(a))
using namespace std;
typedef long long ll;
int hash[N],b[N],a[N];
ll ans,tree[N];
int n,m,cnt;
struct node{
int x,y;
}q[N];
inline int read(){
int a=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(a=0;isdigit(c);a=a*10+c-'0',c=getchar());
return a*f;
}
inline int find(int x) {
int l=1,r=m;
while(l<=r) {
int mid=(l+r)>>1;
if(hash[mid]==x) return mid;
else if(hash[mid]<x) l=mid+1;
else r=mid-1;
}
return r;
}
struct BIT{
int n;
int tre[N];
init(int n){
this-n=n;
memset(tre,false,sizeof(tre));
}
inline int lowbit(int x) {
return x&(-x);
}
inline void add(int x,ll val) {
for (int i=x;i<=m;i+=lowbit(i)) tree[i]+=val;
}
inline ll query(int x) {
ll sum=0;
for (int i=x;i;i-=lowbit(i)) sum+=tree[i];
return sum;
}
int main() {
n=read();
for (int i=1;i<=n;i++) a[++cnt]=q[i].x=read(),a[++cnt]=q[i].y=read();
sort(a+1,a+cnt+1);
for (int i=1;i<=cnt;i++)
if (a[i]!=a[i-1]) hash[++m]=a[i];
for (int i=1;i<=m;i++) b[i]=i;
for (int i=1;i<=n;i++) {
int x=find(q[i].x),y=find(q[i].y);
swap(b[x],b[y]);
}
add(b[m],1);
for (int i=m-1;i;i--) {
ll x=(ll)(hash[i+1]-hash[i]-1),p=query(i);
ans=ans+(x*p);
add(i,x);
ans=ans+query(b[i]-1);
add(b[i],1);
}
printf("%lld",ans);
return 0;
}