Particle

競技プログラミングについての雑記

SRM554 Div1

今回も結果が良くないのに、challengeのお陰で、ratingが上がりました。

Easy

解法

このソースのように場合分けする。
赤と青のレンガの高さが同じ時は、積める個数を数える。
違うときは、赤が1個多い時と、青が1個多い時を区別して数える。

ソース

class TheBrickTowerEasyDivOne{
public:
	int find(int rc, int rh, int bc, int bh) {
		int t = min(rc,bc);
		if(rh==bh){
			if(rc==bc)return (2*t);
			else return (2*t+1);
		}else {
			if(rc==bc)return (3*t);
			else return (3*t+1);
		}
 	}
};

Medium

本番では、ソートしてから、最小値を動かすだけだったので、落ちました。

解法

最小値がどこかにあって、そこを中心にして、外側に単調増加するときに距離が最小となる。
前から見ていって、前の塔より小さければ追加して、大きければ追加しないことを繰り返す。追加出来無かった塔は、最小値の塔よりも右側にあるから、ソートして追加する。
これで、最初の条件を満たして、辞書順で最小のものを作れます。
実際の実装では、追加したりする代わりに、スワップしました。

ソース

class TheBrickTowerMediumDivOne{
public:
	vector <int> find(vector <int> s) {
		int n = s.size();
		if(n==1){
			vector<int> a;
			a.push_back(0);
			return a;
		}
		vector<pair<int,int> > ps(n);
		for(int i = 0; i < n; i++){
			ps[i].first = s[i];
			ps[i].second = i;
		}
		int mn = 50;
		for(int i = 0; i < n; i++){
			mn = min(mn,s[i]);
		}
		bool dec = mn!=s[0];
		for(int i = 1; i < n;){
			if(mn==ps[i].first){
				i++;
				dec = false;
				continue;
			}
			if(dec){
				if(ps[i-1].first<ps[i].first){
					for(int j = i;; j++){
						swap(ps[j],ps[j+1]);
						if(ps[j].first==mn)break;
					}
				}else i++;
			}else {
				vector<pair<int,int> >::iterator it;
				for(it = ps.begin(); *it!=ps[i]; ++it);
				sort(it,ps.end());
				break;
			}
		}
		vector<int> ans(n);
		for(int i = 0; i < n; i++){
			ans[i] = ps[i].second;
		}
		return ans;
	}
};


Rating 1347 -> 1425