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();

	}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章