P4109 [HEOI2015]定价

P4109 [HEOI2015]定价

题目

传送门

思路

直接上算法:

分块

为了尽可能平均,把[0,1e9]分成1e5个块,第i个块为[i*1e4,(i+1)*1e4),不难想到,每一个块的"荒谬度最低的价格"为左端点,即i*1e4,

然后就是分块的老套路:

令p表示l所属的块,q表示r所属的块

  1. p==q:暴力
  2. else:把当前区间分成三段:[l,(p+1)*1e4],[(p+1)*1e4,(q-1)*1e4),[q*1e4,r](注意区分括号的意义,还有就是区间重合对结果无影响),结合上面的结论(加粗部分),可以在O(sqrt(r-l))级别内求出答案

详见代码:

代码

AC程序(tested.cpp)

#include <iostream>
using namespace std;
int a[200010];
int count(int x) {
	while(x % 10 == 0)x/=10;
	int res = (x % 10 == 5 ? -1 : 0);
	while(x != 0) {
		x /= 10;
		res += 2; 
	}
	return res;
}
int GetMin(int l , int r){//暴力求[l,r]的"荒谬度最低的价格"
	int minn = (1 << 29) , ans;
	for(int i = l ; i <= r ; i++) {
		int tmp = count(i);
		if(tmp < minn)
			minn = tmp , ans = i;
	}
	return ans; 
}
int main() {
	int t;
	cin >> t;
	while(t--) {
		int l ,r;
		int minn = (1 << 29) , ans;
		cin >> l >> r;//好久没用过cin/cout了,庆祝一下
		int p = l / 10000 , q = r / 10000;
		if(p == q)
			ans = GetMin(l , r);
		else {
			ans = (p + 1) * 10000;
			minn = count(ans);
			for(int i = ans ; i < r ; i += 10000) {//[(p+1)*1e4,(q-1)*1e4)
				if(count(i) < minn)
					minn = count(i) , ans = i;
			}
			int tmp = GetMin(l , (p + 1) * 10000);//[l,(p+1)*1e4]
			if(count(tmp) < minn)
				minn = count(tmp) , ans = tmp;
				
			tmp = GetMin(q * 10000 , r);//[q*1e4,r]
			if(count(tmp) < minn)
				minn = count(tmp) , ans = tmp;
		} 
		cout << ans << endl;
	}
	return 0;
} 

暴力(std.cpp)

#include <iostream>
using namespace std;
int count(int x) {
	while(x % 10 == 0)x/=10;
	int res = (x % 10 == 5 ? -1 : 0);
	while(x != 0) {
		x /= 10;
		res += 2; 
	}
	return res;
}
int main() {
	int t;
	cin >> t;
	while(t--) {
		int l ,r;
		cin >> l >> r;
		int minn = (1 << 29) , ans;
		for(int i = l ; i <= r ; i++) {
			int tmp = count(i);
			if(tmp < minn)
				minn = tmp , ans = i;
		}
		cout << ans << endl;
	}
	return 0;
} 

对拍用随机数生成器(random.cpp)

#include <bits/stdc++.h>
using namespace std;
int random(int r , int l = 1) {
	return r == l ? l : ((long long)rand() * rand() % (r - l) + l);
}
int main() {
	srand((unsigned)time(0));
	
	int t = random(100);
	cout << t << endl;
	for(int i = 1 ; i <= t ; i++) {
		int l = random(100000000) , r = l + random(1000000);//说明:这里是为了保证暴力程序不超时,可自行加大数据强度
		cout << l << ' ' << r << endl;
	}
	return 0;
}

对拍控制

#include <bits/stdc++.h>
using namespace std;
int main() {
	while(true) {
		system("random.exe > input.txt");
		puts("random");
		
		system("std.exe < input.txt > output1.txt");
		puts("std");
		
		system("tested < input.txt > output2.txt");
		puts("tested");
		
		if(system("fc output1.txt output2.txt")) {
			cout << "WA";
			system("start input.txt");
			return 0;
		}
		
	}
	return 0;
}
原文地址:https://www.cnblogs.com/dream1024/p/14039202.html