[CF1498D]Bananas in a Microwave

壹、题目描述 ¶

传送门 to CF

贰、题解 ¶

最暴力的做法 \(\mathcal O(nm^2)\),但是我们只需要在这上面加一个 “访问到之前已经访问过的节点就不必再访问” 就可以将复杂度降低到 \(\mathcal O(2nm)\),简而言之:

if(vis[cur]) break;

这句话的优化程度是 \(\mathcal O(m)\) 级别的。

何出此言?对于每一个添加一个新的操作 \(\lang t,x,y\rang\),考虑每种点可能的访问次数:

  • 对于未被访问过的点,可能会有很多点都可以扩展到它,但是这些点经过的操作次数是不一样的;
  • 对于被访问过的点,同样有可能有很多点都可以扩展到它,但同时这些点经过的操作次数是不一样的;

好了,如果我们加上上面那句话之后会怎么样?那个剪枝即对于每一个可能被访问到的点,我们都只保留了经过最少操作次数到达它的那一次访问,那么,\(m\) 个点,最多 \(m\) 次访问,但是我们还要再访问曾经被扩展过的节点,这种点最多可能被访问 \(2m\) 次,故纵复杂度达到 \(\mathcal O(2nm)\).

叁、参考代码 ¶

#include<cstdio>
#include<cmath>
#include<bitset>
#include<cstring>
#include<algorithm>
using namespace std;

#define Endl putchar('\n')
#define mp(a, b) make_pair(a, b)
#define rep(i, l, r) for(int i=(l), i##_end_=(r); i<=i##_end_; ++i)
#define fep(i, l, r) for(int i=(l), i##_end_=(r); i>=i##_end_; --i)
#define fi first
#define se second
typedef long long ll;
template<class T>inline T fab(T x){ return x<0? -x: x; }
template<class T>inline T readin(T x){
	x=0; int f=0; char c;
	while((c=getchar())<'0' || '9'<c) if(c=='-') f=1;
	for(x=(c^48); '0'<=(c=getchar()) && c<='9'; x=(x<<1)+(x<<3)+(c^48));
	return f? -x: x;
}

const int maxn=1e5;
const int maxm=200;

inline ll mceil(ll x){
	return (x+maxn-1)/maxn;
}

bitset<maxn+5>vis;
int ans[maxn+5];

int n, m;

inline void trans(ll& cur, int t, ll x){
	if(t==1) cur=cur+mceil(x);
	else cur=mceil(cur*x);
}

signed main(){
	n=readin(1), m=readin(1);
	int t, y; ll x;
	memset(ans, -1, sizeof ans); vis=1;
	rep(i, 1, n){
		t=readin(1), x=readin(1ll), y=readin(1);
		fep(k, m, 0) if(vis[k]){
			ll cur=k; trans(cur, t, x);
			for(int cnt=1; cnt<=y; ++cnt){
				if(cur>m) break;
				if(vis[cur]) break;
				vis[cur]=1, ans[cur]=i;
				trans(cur, t, x);
			}
		}
	}
	rep(i, 1, m) printf("%d ", ans[i]);
	return 0;
}

肆、用到 の Trick ¶

整数上取整:

inline ll mceil(ll x, ll div){
	return (x+div-1)/div;
}

时间复杂度没学懂?

上一篇:Java:如何将HashMap >>写入文件?


下一篇:Python格式化输出