树状数组求逆序数对(两种)

一:

题目链接

In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 

9 1 0 5 4 ,


Ultra-QuickSort produces the output 

0 1 4 5 9 .


Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.

Input

The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.

Output

For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.

Sample Input

5
9
1
0
5
4
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
ll n;
const int maxn = 500001;
struct node{
	ll val,id;
}N[maxn];
ll c[maxn];
int cmp(const node &a,const node& b ){
	if(a.val==b.val)
		return a.id<b.id;
	return a.val<b.val;
}
ll lowbit(int x){
	return x&(-x);
}
void add(int x){
	while(x<=n){
		//排在x地址后面的对比num[i]的影响有意义 
		c[x]++; //可能有重复,因为用++ 不用 = 1;
		x+=lowbit(x);
	}
	return;
}
ll Sum(int x){
	int ans = 0;
	while(x>0){
		ans+=c[x];
		x-=lowbit(x);
	}
	return ans;
}
int main(){
	while(scanf("%lld",&n)&&n){
		for(int i=1;i<=n;i++){
			scanf("%lld",&N[i].val);
			N[i].id=i;
		}
		sort(N+1,N+n+1,cmp);//从 1 - n 排序 
		memset(c,0,sizeof(c));//不要忘记初始化
		long long  ans=0;
		for(ll i=1;i<=n;i++){
			//按照数值从小到大,进行离散化。
			//在其原来的位置上用单位一进行离散化
			//数值小的却在靠后的位置进行离散的话,就会产生逆序
			//注意c[i]数组表示地址小于等于i,数值也小于等于num【i】的数的的个数 
			add(N[i].id);
			ans+=(i-Sum(N[i].id));
		}
		printf("%lld\n",ans);
	}
	return 0;
} 

 

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
ll c[500000],n,d[500001],x[500001];
map<ll,ll> mp;
vector<ll> p;
struct node{
	ll id,val;
	bool operator<(const node &other)const
	{	if(val!=other.val)
		return val<other.val;
		else return id<other.id;
	}
}num[500001];
ll lowbit(ll x){
	return x&(-x);
}
void update(ll pos){
	while(pos<=n){
		c[pos]+=1;
		pos+=lowbit(pos); 
	}
	return ;
}
ll query(ll pos){
	ll sum=0;
	while(pos>0){
		sum+=c[pos];
		pos-=lowbit(pos);
	}
	return sum;
}

int main(){
	while(~scanf("%lld",&n)&&n){
		memset(c,0,sizeof(c));//一开始忘了,老是wa
		p.clear();
		mp.clear();
		ll cnt=1;
		for(ll i=1;i<=n;i++){
		 	scanf("%lld",&x[i]);
		 	if(!mp[x[i]]){
		 		mp[x[i]]=1;
		 		p.push_back(x[i]);
			 }
		}
		sort(p.begin(),p.end());
		ll len=p.size();
        //离散化
		for(ll i=0;i<len;i++){
			mp[p[i]]=cnt++;
		}
		cnt--;
		for(ll i=1;i<=n;i++){
			num[i].val=mp[x[i]];
			num[i].id=i;
		}
		sort(num+1,num+1+n);
		ll ans=0;
		for(ll i=1;i<=n;i++){
			update(num[i].id);
			ans+=(i-query(num[i].id)); 
		}
		printf("%lld\n",ans);
	}
	return 0;
}
//            /\       |  /  |**、
//			 /  \      | /   |   \
//			/    \     |/    |   /  _____                      ____   |  /
//		   /------\    |\    |__/  /     \  \      /\      /  /    \  | /
//		  /        \   | \   |    /       \  \    /  \    /  /______\ |/
//		 /          \  |  \  |    \       /   \  /    \  /   \        |
//      /            \ |   \ |     \_____/     \/      \/     \_____  |
/**
 *        ┏┓    ┏┓
 *        ┏┛┗━━━━━━━┛┗━━━┓
 *        ┃       ┃  
 *        ┃   ━    ┃
 *        ┃ >   < ┃
 *        ┃       ┃
 *        ┃... ⌒ ...  ┃
 *        ┃       ┃
 *        ┗━┓   ┏━┛
 *          ┃   ┃ Code is far away from bug with the animal protecting          
 *          ┃   ┃   神兽保佑,代码无bug
 *          ┃   ┃           
 *          ┃   ┃        
 *          ┃   ┃
 *          ┃   ┃           
 *          ┃   ┗━━━┓
 *          ┃       ┣┓
 *          ┃       ┏┛
 *          ┗┓┓┏━┳┓┏┛
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛
 */
// warm heart, wagging tail,and a smile just for you!
//
//                            _ooOoo_
//                           o8888888o
//                           88" . "88
//                           (| -_- |)
//                           O\  =  /O
//                        ____/`---'\____
//                      .'  \|     |//  `.
//                     /  \|||  :  |||//  \
//                    /  _||||| -:- |||||-  \
//                    |   | \\  -  /// |   |
//                    | \_|  ''\---/''  |   |
//                    \  .-\__  `-`  ___/-. /
//                  ___`. .'  /--.--\  `. . __
//               ."" '<  `.___\_<|>_/___.'  >'"".
//              | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//              \  \ `-.   \_ __\ /__ _/   .-` /  /
//         ======`-.____`-.___\_____/___.-`____.-'======
//                            `=---='
//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//

二:

 题目链接

There is an infinite sequence consisting of all positive integers in the increasing order: p = {1, 2, 3, ...}. We performed n swap operations with this sequence. A swap(a, b) is an operation of swapping the elements of the sequence on positions aand b. Your task is to find the number of inversions in the resulting sequence, i.e. the number of such index pairs (i, j), that i < j and pi > pj.

Input

The first line contains a single integer n (1 ≤ n ≤ 105) — the number of swapoperations applied to the sequence.

Each of the next n lines contains two integers ai and bi (1 ≤ ai, bi ≤ 109, ai ≠ bi) — the arguments of the swap operation.

Output

Print a single integer — the number of inversions in the resulting sequence.

Examples

Input

2
4 2
1 4

Output

4

Input

3
1 6
3 4
2 5

Output

15

Note

In the first sample the sequence is being modified as follows: . It has 4 inversions formed by index pairs (1, 4), (2, 3), (2, 4) and (3, 4).

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
ll c[400001],f[400001],n,x[100001],y[100001],d[400001],cnt;
struct node{
	ll id,val;
	bool operator<(const node &other)const
	{
		return val<other.val;
	}
}num[400000];
vector<ll> p;
map<ll,ll> mp;
map<ll,ll> m;
ll lowbit(ll x){
	return x&(-x);
}
void update(ll pos,ll y){
	while(pos<=cnt){
		c[pos]+=y;//上一题相当于y=1 
		pos+=lowbit(pos);
	}
}
ll getsum(ll pos){
	ll sum=0;
	while(pos>0){
		sum+=c[pos];
		pos-=lowbit(pos);
	}
	return sum;
}

int main(){
	cin>>n;
	for(ll i=1;i<=n;i++){
		cin>>x[i]>>y[i];
		//去重,最好不要在下面用unique,容易出错 
		if(!m[x[i]]){
		p.push_back(x[i]);
		m[x[i]]=1;
		}
		if(!m[y[i]]){
		p.push_back(y[i]);
		m[y[i]]=1;
		}
	}
	sort(p.begin(),p.end());//排序 
	ll len=p.size();
	cnt=1;
	//用于交换的点看做点,不交换的点在同一个区间内的看做一个点,离散化 
	for(size_t i=0;i<len;i++){
		if(i==0){//把第一个交换的点赋值为华为1 
			f[cnt]=1;//f[i]表示第i个数表示几个数 
//			d[cnt]=cnt;
			mp[p[i]]=1;
			cnt++;
			continue;
		}
		if(p[i]-p[i-1]>1){
			f[cnt]=p[i]-p[i-1]-1;
//			d[cnt]=cnt;
			cnt++;
			f[cnt]=1;
//			d[cnt]=cnt;
			mp[p[i]]=cnt;
			cnt++;
			continue;
		}
		if(p[i]-p[i-1]==1){
		f[cnt]=1;
//		d[cnt]=cnt;
		mp[p[i]]=cnt;
		cnt++;
		continue;
		}
	}
	cnt--;
	for(ll i=1;i<=cnt;i++){
		c[i]=0;
	}
	//对d[]的赋值可以在离散化的步骤中 
	for(ll i=1;i<=cnt;i++){
		d[i]=i;
	}
	for(ll i=1;i<=n;i++){
		ll tx=mp[x[i]];
		ll ty=mp[y[i]];
		swap(d[tx],d[ty]);
	}
	for(ll i=1;i<=cnt;i++){
		num[i].id=i;
		num[i].val=d[i];
	}
	sort(num+1,num+1+cnt);
	ll ans=0,tot=0;
	//接下来可以不用num[]结构体,可以直接用d[]数组 
	///d[i]就代表第i个数原来的位置
	//习惯用num[],但是下一个更快 
	//此题的tot相当于上一题的i 
	for(ll i=1;i<=cnt;i++){
		tot+=f[num[i].val];//累积 
		update(num[i].id,f[num[i].val]);
		ans+=(tot-getsum(num[i].id))*f[num[i].val];//记住 
	}
//		for(ll i=1;i<=cnt;i++){
//		tot+=f[i];
//		update(d[i],f[i]);
//		ans+=(tot-getsum(d[i]))*f[i];
//	} 
	printf("%I64d\n",ans);
	return 0;
}



/**
 *        ┏┓    ┏┓
 *        ┏┛┗━━━━━━━┛┗━━━┓
 *        ┃       ┃  
 *        ┃   ━    ┃
 *        ┃ >   < ┃
 *        ┃       ┃
 *        ┃... ⌒ ...  ┃
 *        ┃       ┃
 *        ┗━┓   ┏━┛
 *          ┃   ┃ Code is far away from bug with the animal protecting          
 *          ┃   ┃   神兽保佑,代码无bug
 *          ┃   ┃           
 *          ┃   ┃        
 *          ┃   ┃
 *          ┃   ┃           
 *          ┃   ┗━━━┓
 *          ┃       ┣┓
 *          ┃       ┏┛
 *          ┗┓┓┏━┳┓┏┛
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛
 */
// warm heart, wagging tail,and a smile just for you!
//
//                            _ooOoo_
//                           o8888888o
//                           88" . "88
//                           (| -_- |)
//                           O\  =  /O
//                        ____/`---'\____
//                      .'  \|     |//  `.
//                     /  \|||  :  |||//  \
//                    /  _||||| -:- |||||-  \
//                    |   | \\  -  /// |   |
//                    | \_|  ''\---/''  |   |
//                    \  .-\__  `-`  ___/-. /
//                  ___`. .'  /--.--\  `. . __
//               ."" '<  `.___\_<|>_/___.'  >'"".
//              | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//              \  \ `-.   \_ __\ /__ _/   .-` /  /
//         ======`-.____`-.___\_____/___.-`____.-'======
//                            `=---='
//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值