poj2299(离散化)

离散化:当给出的一组数据的范围较大,而个数较少时,可以将这组数据离散化。例如,数组9,5,2,1,7离散化后变为5,3,2,1,4。以备例如开数组计算各值个数或建树状数组之需。

离散化方法之一——对存在重复数字的数组,使得相等的值在离散化后依然相等——步骤:
1.数组a存放原始数据n个
2.new一个SortedSet集合set,将a中元素add到set中。(set只可以存放不相同的数字,并将其从小到大排序)
3.将set中的元素按顺序存放到数组b中。
4.将a元素替换为b中相等元素的下标值+1,即可得到离散化数组a
注意:
1.注意b的大小为set的大小,而非a的大小n!!
2.对无法随机读取的集合类,java提供了一种方法即:

int ct=0;
for(int cur:set) {
				b[ct++]=cur;
				//System.out.println(b[ct-1]);
			}

来方便地遍历并存入普通数组。
3.树状数组的下标必须从1开始,不能是0,lowbit对0没有办法。
4.因此,每一次对c[]清零时,都不要忘了让i<=n那个等号啊啊啊 debug半天。
5.关于lowerbound,之前的博客有讲。

以下是Poj2299 AC代码




public class test2 {

	static int maxn=500010,n;
	static long c[]=new long[maxn];
	public static long lowbit(long x) {
		return x&(-x);
	}
	public static void add(long x,int k) {
		//System.out.println(x+" "+n);
		while(x<=n) {
			c[(int) x]+=k;
			x+=lowbit(x);
		}
	}
	public static int getsum(long x) {//求前x项和
		int ans=0;
		while(x>0) {
			ans+=c[(int) x];
			x-=lowbit(x);
		}
		return ans;
	}
	public static int lower_bound(long[] a,long x) {

		int l=-1,r=b.length-1,mid=0;
		while(r-l>1) {
			mid=(l+r)/2;
			if(a[mid]>=x) {
				r=mid;
			}else {
				l=mid;
			}
		}
		return r;
	}
	static long b[];
	public static void main(String args[]) throws IOException {
		long a[]=new long[maxn];
		InputReader in=new InputReader(System.in);
		SortedSet<Long> set=new TreeSet<Long>();
		
		n=in.nextInt();
		while(n!=0) {
			long ans=0;
			set.clear();
			for(int i=0;i<=n;i++) {
				c[i]=0;
			}
		//离散化,最终使a成为原a的离散化数组
			for(int i=0;i<n;i++) {
				a[i]=in.nextLong();
				set.add(a[i]);
			}
			//将去重排序的set集合值赋给b
			b=new long[set.size()];
			int ct=0;
			for(Long cur:set) {
				b[ct++]=cur;
				//System.out.println(b[ct-1]);
			}

			for(int i=0;i<n;i++) {
				a[i]=1+lower_bound(b, a[i]);
				//System.out.println(a[i]);
				
			}
			
			//树状数组
			for(int i=0;i<n;i++) {
				ans+=i-getsum(a[i]);
				//System.out.println(a[i]+" "+getsum(a[i]));
				add(a[i],1);
			}
			System.out.println(ans);
			n=in.nextInt();
		}
		
	}	
}

离散化方法之二:原数组重复元素离散化后不等——

class node{
	int v, id;
}
public static void main(String args[]) {
		int n,maxn;
		node arr[]=new node[maxn];
		for(int i=0;i<n;i++) {
			arr[i].v=sc.nextInt();
			arr[i].id=i;
		}
		Arrays.sort(arr,0,n);
		int a[]=new int[maxn];
		for(int i=1;i<=n;i++) {
			a[arr[i].id]=i;
		}
		//得到a为arr离散化后数组
	}
	```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值