Particle

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

AOJ 2374 : RabbitLunch

解法

sort+累積和+setで解こうとするとsetのメモリの定数倍が大きくMLEするので、
尺取法みたいな感じ(?)で次数を1つずつ順に見ながら、最小カットを考えるとO(n)で解けて、メモリも足りる。

#include <iostream>
using namespace std;
typedef long ll;
#define N 2500001
int x[N], y[N], x2[N], y2[N];

int main(){
	int n, m, b, d;
	cin>>n>>m>>x[0]>>b>>y[0]>>d;
	ll res = x[0];
	x2[0] = 1;
	y2[n+1] = 1;
	x2[x[0]]++;
	for(int i = 1; i < n; i++){
		x2[x[i]=(58*x[i-1]+b)%(m+1)]++;
		res += x[i];
	}
	y2[y[0]]++;
	for(int i = 1; i < m; i++){
		y2[y[i]=(58*y[i-1]+d)%(n+1)]++;
	}
	ll sum = res, pos = m, pos2 = 0, cnt = 0, cnt2 = m;
	while(x2[pos]==0) pos--;
	while(y2[pos2]==0) pos2++;
	while(pos>0){
		sum -= pos;
		cnt++;
		x2[pos]--;
		while(x2[pos]==0) pos--;
		while(cnt2 && cnt >= pos2){
			sum += pos2;
			cnt2--;
			y2[pos2]--;
			while(y2[pos2]==0) pos2++;
		}
		if(res>sum+cnt*cnt2) res = sum+cnt*cnt2;
	}
	cout<<res<<endl;
	
	return 0;
}

MLEする方

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
typedef long ll;
#define N 2500000
set<int> st;
int x[N], y[N];

int main(){
	int n, m, a, b, c, d;
	cin>>n>>m>>a>>b>>c>>d;
	x[0] = a;
	for(int i = 1; i < n; i++) x[i] = (58*x[i-1]+b)%(m+1);
	sort(x, x+n);
	y[0] = c;
	for(int i = 1; i < m; i++) y[i] = (58*y[i-1]+d)%(n+1);
	sort(y, y+m);
	for(int i = m-1; i > 0; i--) y[i]-=y[i-1];
	st.insert(-1);
	st.insert(m);
	for(int i = 0; i < m; i++)
		if(y[i]) st.insert(i);
	ll res = 0;
	for(int i = n-1; i >= 0; i--){
		int deg = x[i];
		auto it = st.lower_bound(m-deg);
		int num = *it;
		if(num < m){
			if(--y[num] == 0) st.erase(it);
		}
		int deg2 = deg-m+num;
		if(deg2){
			auto it2 = st.lower_bound(m-deg);
			--it2;
			num = *it2;
			if(num >= 0){
				if(--y[num] == 0) st.erase(it2);
				if(y[num+deg2]++ == 0) st.insert(num+deg2);
				deg2 = 0;
			}
		}
		res += deg-deg2;
	}
	cout<<res<<endl;
	
	return 0;
}