CF#136

A. Little Elephant and Problem

题意:给出一个数组,问是否是由一个已排序的数组经过交换至多一对数得到。

解法:将给定的数组排序后与元数组比较,若有多于两个位置不同则不是,否则将原数组两个位置的数字交换后比较是否与排序后数组相同。

B. Little Elephant and Array

题意:给出一个数组,问某个自区间内有多少个x出现了x次。

解法:对与大于n的数,直接忽略。两种做法:

1.类似于hdu4358http://blog.csdn.net/kksleric/article/details/7935277

2.考虑整个区间内出现过x次的值x最多有sqrt(n)个,因此逐一处理这样的元素,离线处理每个查询去子区间内有多少个此x,最后输出。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.TreeMap;

public class d {
	int maxn = 100010;
	StreamTokenizer in = new StreamTokenizer(new BufferedReader(
			new InputStreamReader(System.in)));
	int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}
	int arr[] = new int[maxn],num[] = new int[maxn], sum[] = new int[maxn];
	int left[] = new int[maxn], right[] = new int[maxn], ans[] = new int[maxn];
	void run() throws IOException {
		int n = nextInt();
		int m = nextInt();
		for (int i = 1; i <= n; i++) {
			arr[i] = nextInt();
			if (arr[i] > n)
				arr[i] = 0;
			num[arr[i]]++;
		}
		for (int i = 1; i <= m; i++) {
			left[i] = nextInt();
			right[i] = nextInt();
		}
		for (int i = 1; i <= n; i++)
			if (arr[i] != 0 && num[arr[i]] >= arr[i]) {
				num[arr[i]] = 0;
				for (int j = 1; j <= n; j++) {
					sum[j]=sum[j-1];
					if(arr[j]==arr[i])
						sum[j]++;
				}
				for(int j=1;j<=m;j++)
					if(sum[right[j]]-sum[left[j]-1]==arr[i])
						ans[j]++;
			}
		for(int i=1;i<=m;i++)
			System.out.println(ans[i]);
	}

	public static void main(String[] args) throws IOException {
		new d().run();
	}
}

C. Little Elephant and Shifts

题意:给出ab两个排列,连个排列之间的距离定义为每个元素index距离差绝对值的最小值,问b排列左移1、2、3、4、5---n-1次后两排列的距离。

解法:由于距离的定义为绝对值的最小值,因此分负数和正数两种情况考虑,设每个元素的初始距离为x[i]则对于x[i]为负数的点,除当前第一个元素外每次移动都会减小,即仍为负数,第一个元素的距离移到追尾变为非负数;对于x[i]为非负数的点,移动x[i]+1次后变成负数;

因此开两个map分别维护负值x和正值x,当正负号方式改变时从一个map移到另一个map,为便于维护,我们插入的值都是相对大小,在去除最小值之后加上偏移(移动次数)得到当前最小距离。

import java.util.Scanner;
import java.util.TreeMap;
public class Shift220C {
	class MAP {
		TreeMap<Integer, Integer> mp = new TreeMap<Integer, Integer>();
		void add(int k, int t) {
			if (t == 0)
				return;
			if (mp.containsKey(k))
				mp.put(k, t + mp.get(k));
			else
				mp.put(k, t);
		}
		void del(int k, int t) {
			if (t == 0)
				return;
			if (!mp.containsKey(k))
				return;
			if (mp.get(k) == t)
				mp.remove(k);
			else
				mp.put(k, mp.get(k) - t);
		}
		int getmin() {
			if (mp.isEmpty())
				return inf;
			return mp.firstKey();
		}
		int getmax() {
			if (mp.isEmpty())
				return -inf;
			return mp.lastKey();
		}
	}
	int inf = 1 << 28, maxn = 100010;
	MAP neg = new MAP(), pos = new MAP();
	int pa[] = new int[maxn], b[] = new int[maxn];
	int num[] = new int[maxn * 2], x[] = new int[maxn];
	Scanner scan = new Scanner(System.in);
	void run() {
		int n = scan.nextInt();
		for (int i = 1; i <= n; i++)
			pa[scan.nextInt()] = i;
		for (int i = 1; i <= n; i++) {
			b[i] = scan.nextInt();
			x[i] = i - pa[b[i]];
			if (x[i] < 0)
				neg.add(x[i], 1);
			else {
				num[x[i]]++;
				pos.add(x[i], 1);
			}
		}
		System.out.println(Math.min(-neg.getmax(), pos.getmin()));
		for (int i = 1; i < n; i++) {
			if (x[i] + 1 < i)
				neg.del(x[i], 1);
			else {
				pos.del(x[i], 1);
				num[x[i]]--;
			}
			int temp = n - pa[b[i]] + i;
			pos.add(temp, 1);
			num[temp]++;
			pos.del(i - 1, num[i - 1]);
			neg.add(i - 1, num[i - 1]);
			System.out.println(Math.min(-neg.getmax() + i, pos.getmin() - i));
		}
	}

	public static void main(String[] args) {
		new Shift220C().run();
	}
}

E. Little Elephant and Inversions

题意:how many pairs of integers l and r are there, such that 1 ≤ l < r ≤ n and sequence b = a1a2... alarar + 1... an has no more than k inversions.

解法:首先观察单调性,若<l,r>符合要求则<l+i,r+i>也符合要求,因此题目变为对于一个固定的r,找出最大的l使得满足要求。首先求出这个区间的逆数对数,然后使用two pointers,使得每个元素入队出队一次,同时使用树状数组维护每个元素构成的逆序对数,求出最大r后统计答案。(固定l需找最小的r貌似维护起相对麻烦),注意b要包含al和ar,统计时需要特判。

import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;

public class Inversions220E {
	int maxn = 100010;
	class IndexTree {
		int ss[] = new int[maxn + 10];
		int N = maxn;
		int lowbit(int k) {
			return (k & -k);
		}
		void inc(int i, int v) {
			while (i <= N) {
				ss[i] += v;
				i += lowbit(i);
			}
		}
		int get(int i) {
			int res = 0;
			while (i > 0) {
				res += ss[i];
				i -= lowbit(i);
			}
			return res;
		}
	}
	IndexTree all = new IndexTree(), pre = new IndexTree(),
			now = new IndexTree();
	TreeMap<Integer, Integer> mp = new TreeMap<Integer, Integer>();
	int arr[] = new int[maxn];
	Scanner scan = new Scanner(System.in);
	void run() {
		int n = scan.nextInt();
		long k = scan.nextLong();
		long sum = 0, ans = 0;
		for (int i = 1; i <= n; i++) {
			arr[i] = scan.nextInt();
			mp.put(arr[i], 0);
		}
		int cnt = 0;
		Set<Integer> set = mp.keySet();
		for (int i : set)
			mp.put(i, ++cnt);
		for (int i = 1; i <= n; i++) {
			arr[i] = mp.get(arr[i]);
			all.inc(arr[i], 1);
			sum += i - all.get(arr[i]);
		}
		if(sum<=k)
		{
			ans=1l*n*(n-1)/2;
			System.out.println(ans);
			return;
		}
		int left = 1, right =1;
		now.inc(arr[1],1);
		long res=sum-all.get(arr[1]-1);
		while (left <= n) {
			while (right <=n && res> k) {	
				right++;	
				now.inc(arr[right], 1);		
				res-=left-1-pre.get(arr[right]);
				res-=all.get(arr[right]-1)-now.get(arr[right]-1)-pre.get(arr[right]-1);
			}
			while (left<right) {
				long temp = left - 1 - pre.get(arr[left]);
				temp += all.get(arr[left] - 1) - pre.get(arr[left] - 1)-now.get(arr[left]-1);
				if(res+temp > k)
					break;
				pre.inc(arr[left],1);
				now.inc(arr[left],-1);
				res+=temp;
				left++;
			}
			if (res<=k&&left!=1&&right!=n)
				ans += left-1;
			if(right==n)
				break;
			right++;
			now.inc(arr[right], 1);		
			res-=left-1-pre.get(arr[right]);
			res-=all.get(arr[right]-1)-now.get(arr[right]-1)-pre.get(arr[right]-1);
		}
		System.out.println(ans);
	}
	public static void main(String[] args) {
		new Inversions220E().run();

	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值