Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

分享一个自己写的树状数组求逆序数的O(nlogn)ac代码

Posted by z85769597 at 2015-04-19 13:26:23 on Problem 1007
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

int n,m;
char s[110][60];
int c[60];
typedef pair<char,int>P;
typedef pair<int,int>P1;

int cmp(P p1,P p2)
{
	return p1.first<p2.first;
}
int lowbit(int x)
{
	return x&(x^(x-1));
}
void add(int i,int x)
{
	while(i<=n)
	{
		c[i]+=x;
		i+=lowbit(i);
	}
}
int Sum(int i)
{
	int s=0;
	while(i>0)
	{
		s+=c[i];
		i-=lowbit(i);
	}
	return s;
}
int Inversion(char * s)
{
	memset(c,0,sizeof(c));
	P p[60];
	int cnt[60]={0};
	int i;
	for(i=0;i<n;i++)		
	{
		p[i+1].first=s[i];
		p[i+1].second=i+1;
	}
	sort(p+1,p+1+n,cmp);
	int id=1;
	cnt[p[1].second]=id;
	for(i=2;i<=n;i++)			//离散化
	{
		if(p[i].first==p[i-1].first)
			cnt[p[i].second]=id;
		else
			cnt[p[i].second]=++id;
	}
	int sum=0;
	for(i=1;i<=n;i++)		//插入
	{
		add(cnt[i],1);		//在离散化后的cnt[i]位置插入1
		sum+=i-Sum(cnt[i]);
	}
	return sum;
}

class cmp1
{
public:
	bool operator()(P1 &a,P1 &b)//按逆序对数从小到大输出,如数量一样,按原始下标输出。
	{
		if(a.first!=b.first)
		return a.first>b.first;	//first是逆序对数,second是输入的第几个字符串
		return a.second>b.second;
	}
};
int main()
{
//	freopen("C:\\1.txt","r",stdin);
	cin>>n>>m;
	int i;
	priority_queue<P1,vector<P1>,cmp1>q;	//最终输出的队列
	for(i=1;i<=m;i++)
	{
		scanf("%s",s[i]);
		int num=Inversion(s[i]);		//树状数组求逆序对数量
		q.push(P1(num,i));			//入队列等待输出
	}
	while(!q.empty())
	{
		P1 x=q.top();
		printf("%s\n",s[x.second]);
		q.pop();
	}
}

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator