Train Car Selection「CF1137E」/序列舞蹈「NOIP多校联考 2019」

题意

给出一个序列,初始时序列的长度为 n,序列中每个数为 0。
进行 m 次操作,操作有三种:
1 k 在序列开头加入 k 个数字 0
2 k 在序列末尾加入 k 个数字 0
3 b s 给序列中所有数字加上 b+s*(i-1) [i 是该数字在序列中的位置]
你需要在每次操作后输出序列中最小的数字大小和位置,如果有多个最小的数字,输出最靠前的一个


思路

又是一道CF换头题。

正解完全没想到,但是由于考试的时候是随机数据,所以可以使用乱搞方法切掉。

本质上是朴素的暴力,均摊复杂度为\(O(m)\)(尽管可以被卡成\(O(m^2)\)

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

	template<typename T>inline void read (T &x) {
		x=0;T f=1;char c=getchar();
		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
		x*=f;
	}

	template<typename T>inline void write (T x) {
		if (x<0) putchar('-'),x*=-1;
		if (x>=10) write(x/10);
		putchar(x%10+'0');
	}

}

using namespace StandardIO;

namespace Project {
	#define int long long
	
	const int N=100100;
	
	int n,m,len,top;
	pair<int,int> ans,answer[N],tmp[N];
	
	inline void query () {
		int ll=0;
		ans.second=0x7fffffff;
		for (register int i=1; i<=top; ++i) {
			if (ans.second>answer[i].second) ans=answer[i],tmp[++ll]=ans;
		}
		for (register int i=1; i<=ll; ++i) {
			answer[i]=tmp[i];
		}
		top=ll;
	}

	inline void MAIN () {
		read(n),read(m),ans=make_pair(0,0),len=n-1,answer[++top]=ans;
		for (register int i=1,op,x,y; i<=m; ++i) {
			read(op);
			if (op==1) { 
				read(x),top=1;
				answer[top]=ans=make_pair(0,0);
				len+=x;
			} else if (op==2) {
				read(x);
				answer[++top]=make_pair(len+1,0);
				query();
				len+=x;
			} else {
				read(x),read(y);
				for (register int i=1; i<=top; ++i) answer[i].second+=x+y*answer[i].first;
				query();
			}
			write(ans.first+1),putchar(' '),write(ans.second),putchar('\n');
		}
	}
	
	#undef int
}

int main () {
//	freopen("1.in","r",stdin);
//	freopen("2.out","w",stdout);
	Project::MAIN();
}
posted @ 2019-10-04 16:16  Ilverene  阅读(286)  评论(0编辑  收藏  举报