D. Bananas in a Microwave CodeCraft-21 and Codeforces Round #711 (Div. 2)

D. Bananas in a Microwave
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You have a malfunctioning microwave in which you want to put some bananas. You have n time-steps before the microwave stops working completely. At each time-step, it displays a new operation.

Let k be the number of bananas in the microwave currently. Initially, k=0. In the i-th operation, you are given three parameters ti, xi, yi in the input. Based on the value of ti, you must do one of the following:

Type 1: (ti=1, xi, yi) — pick an ai, such that 0≤ai≤yi, and perform the following update ai times: k:=⌈(k+xi)⌉.

Type 2: (ti=2, xi, yi) — pick an ai, such that 0≤ai≤yi, and perform the following update ai times: k:=⌈(k⋅xi)⌉.

Note that xi can be a fractional value. See input format for more details. Also, ⌈x⌉ is the smallest integer ≥x.

At the i-th time-step, you must apply the i-th operation exactly once.

For each j such that 1≤j≤m, output the earliest time-step at which you can create exactly j bananas. If you cannot create exactly j bananas, output −1.

Input
The first line contains two space-separated integers n (1≤n≤200) and m (2≤m≤105).

Then, n lines follow, where the i-th line denotes the operation for the i-th timestep. Each such line contains three space-separated integers ti, x′i and yi (1≤ti≤2, 1≤yi≤m).

Note that you are given x′i, which is 105⋅xi. Thus, to obtain xi, use the formula xi=x′i105.

For type 1 operations, 1≤x′i≤105⋅m, and for type 2 operations, 105<x′i≤105⋅m.

Output
Print m integers, where the i-th integer is the earliest time-step when you can obtain exactly i bananas (or −1 if it is impossible).

Examples
inputCopy
3 20
1 300000 2
2 400000 2
1 1000000 3
outputCopy
-1 -1 1 -1 -1 1 -1 -1 -1 3 -1 2 3 -1 -1 3 -1 -1 -1 3
inputCopy
3 20
1 399999 2
2 412345 2
1 1000001 3
outputCopy
-1 -1 -1 1 -1 -1 -1 1 -1 -1 3 -1 -1 -1 3 -1 2 -1 3 -1
Note
In the first sample input, let us see how to create 16 number of bananas in three timesteps. Initially, k=0.

In timestep 1, we choose a1=2, so we apply the type 1 update — k:=⌈(k+3)⌉ — two times. Hence, k is now 6.
In timestep 2, we choose a2=0, hence value of k remains unchanged.
In timestep 3, we choose a3=1, so we are applying the type 1 update k:=⌈(k+10)⌉ once. Hence, k is now 16.
It can be shown that k=16 cannot be reached in fewer than three timesteps with the given operations.

In the second sample input, let us see how to create 17 number of bananas in two timesteps. Initially, k=0.

In timestep 1, we choose a1=1, so we apply the type 1 update — k:=⌈(k+3.99999)⌉ — once. Hence, k is now 4.
In timestep 2, we choose a2=1, so we apply the type 2 update — k:=⌈(k⋅4.12345)⌉ — once. Hence, k is now 17.
It can be shown that k=17 cannot be reached in fewer than two timesteps with the given operations.

调了一个下午,终于拨云见日
物理老师:没有你的每一次失败,你最后能成功吗

1、开始想跑一个最短路,后来发现只要都连0,不要建图
2、之后就是超时,又是剪枝
——剪枝秘诀:找相同状态,即能产生相同结果的一些汇集点,只走一次
比如旅行商问题也是。
我只发现了次数少的节点要continue,但是应该break
这里上一个数plus操作相同能结果相同
每次循环的操作相同,所以汇集点是数字相同,之前算了就不要算,break了
bool数组不要,也耗时,可以发现这里恰可以dis有没有初始化看要不要看
3、一些WA:
下标i,j区分
O3优化可能害人
一些时间优化
forauto可能没有迭代器高效
复制元素好像还不如空跑些循环,反正会剪枝
set比vector浪费的是10多倍时间,高度10多
4、一个函数:ceil(x)[和floor(x)]
5、一个迭代器:set< T >::iterator iter = vis.begin();

//#pragma GCC optimize(3,"Ofast","inline")
//#pragma GCC optimize(2)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include<iostream>
#include<algorithm>
//#include<string>
//#include<sstream>
#include<vector>
//#include<map>
#include<set>
//#include<ctype.h>
//#include<stack>
#include<queue>
#ifdef LOCAL
FILE*FP=freopen("text.in","r",stdin);
//FILE*fp=freopen("text.out","w",stdout);
#endif
using namespace std;
#define ll long long
#define ld long double
#define pii pair<int,int>
#define piii pair<int,pii>
#define pll pair<ll,ll>
#define plll pair<ll,pll> 
#define pdd pair<double,double>
#define pdi pair<double,int>
#define pid pair<int,double>
#define vi vector <int> 
#define vii vector <vi> 
#define vl vector<ll>
#define st first
#define nd second
#define pb push_back
#define mp make_pair
#define mem(a,b) memset(a,b,sizeof(a))
#define _forplus(i,a,b) for( register int i=(a); i<=(b); i++)
#define forplus(i,a,b) for( register int i=(a); i<(b); i++)
#define _forsub(i,a,b) for( register int i=(a); i>=(b); i--)
#define _forauto(a,b) for(auto &(a):(b))//这个是返回元素,如map的a.nd 
#define _forautome(a,b,c) for(auto (a) = (b); (a) != (c); (a)++)//这个是返回指针,如map的a->nd 
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define pi (acos(-1))
#define EPS 0.00000001
#define MOD 1000000007
#define fastio 	std::ios::sync_with_stdio(false);std::cin.tie(0);
#define M 200005
#define int ll
int dis[M];//距离 
//set<int>vis;//建图用
vector<int>vis;//现在只要vector了 ——都不要了 
int n,m,t,cx,y;//n次操作,m+1个节点 
//double x;
vector<int>temp; 
//set<int>temp;
void have(int t,int cx,int y,int v){
	//temp.clear();//记得清空 ,是clear ,empty是看是否空 
	//set<int>::iterator iter = vis.begin();
	//while (iter!=vis.end())
	forplus(i,0,vis.size())
	{
	//_forauto(k,vis){//传指针才是更高效的!!! 
	//	temp.pb(k);
	//}//存个副本,不然等下插入后就多了事(或者存产生的副本,个数更多——其实后期这样更少!!) 
	//_forauto(k,temp){
		int c=vis[i];
		_forplus(J,1,y){
			if(t==1){
				c=ceil(c+cx/100000.0);
			}else{
				c=ceil(c*(cx)/100000.0);
			}
			if(c==vis[i])break;//避免重复输入 ,注意xy重复 
			if(c>m)break; 
			//auto f=vis.find(c);
			//if(f==vis.end()){
			//if(vis.count(c)==0){//这里慢了,比bool数组 。改成dis[c]<LINF是一大优化 
			if(dis[c]==LINF){
				temp.pb(c); //这里可能会重复输入 
				//vis.insert(c);
				dis[c]=v;
			}else{
				break;//关键!因为都是相同的操作,所以就可以剪枝,类似旅行商问题状压DP 
			}
		}
		//iter++;
	}
	forplus(i,0,temp.size()){
		vis.pb(temp[i]);
	}
	temp.clear();
}
//为什么用set,直接用bool数组不是更香吗。这毒瘤题。。——插入后期太搞了 
int32_t main()
{
	fastio
	cin>>n>>m;
	vis.pb(0);
	mem(dis,0x3f);
	dis[0]=0;
	_forplus(i,1,n){
		cin>>t>>cx>>y;
		//x=cx/100000.0;//浮点数误差,不要 
		have(t,cx,y,i); 
	}
	_forplus(i,1,m){
		//cout<<(dis[i]==LINF?-1:dis[i])<<' ';
		printf("%lld ",dis[i]==LINF?-1:dis[i]);
	}
	//cout<<'\n';
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值