[CF1498D]Bananas in a Microwave
作者:互联网
壹、题目描述 ¶
贰、题解 ¶
最暴力的做法 \(\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;
}
时间复杂度没学懂?
标签:Bananas,vis,int,ll,Microwave,readin,访问,CF1498D,cur 来源: https://www.cnblogs.com/Arextre/p/14729144.html