test20181024 kun
题意
分析
考场做法
任意状态只有两种决策,进栈或出栈。
由于元素互不相同,所以选择的关键在于栈顶元素是否在它和带插入元素组成的集合中是最大的。
用stack和set维护。时间复杂度\(O(n \log n)\)
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#include<cassert>
#define rg register
#define il inline
#define co const
#pragma GCC optimize ("O0")
using namespace std;
template<class T> il T read()
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return data*w;
}
template<class T> il T read(T&x)
{
return x=read<T>();
}
typedef long long ll;
const int INF=0x7fffffff;
const int MAXN=1e6+7;
int a[MAXN];
stack<int>S;
set<int>H;
int main()
{
freopen("kun.in","r",stdin);
freopen("kun.out","w",stdout);
rg int n=read<int>();
for(rg int i=1;i<=n;++i)
{
read(a[i]);
H.insert(a[i]);
}
rg int p=1;
for(rg int i=1;i<=2*n;++i)
{
// cerr<<"pro "<<i<<endl;
if(!S.empty()&&S.top()==*H.rbegin()) // pop
{
// cerr<<" case 1"<<endl;
printf("%d ",S.top());
H.erase(S.top());
S.pop();
if(!S.empty())
H.insert(S.top());
}
else // push
{
// cerr<<" case 2"<<endl;
if(!S.empty())
H.erase(S.top());
S.push(a[p++]);
}
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
标解
要使序列字典序最大,首先它的第一个元素必须是最大元素,按此思路贪心即可。要求出下一步可输出元素的最大者,只需要取下一个元素所在的后缀与当前栈顶元素中的最大值。后缀最大值可以在线性时间内预处理出。
实际上维护最大值没必要用set,观察发现我们只需了解每个后缀的最大值,所以用数组维护。
时间复杂度\(O(n)\)
//Achen
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
#define Formylove return 0
const int N=1e6+7;
typedef long long LL;
typedef double db;
using namespace std;
int n,a[N],mx[N];
template<typename T> void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
int sta[N],top;
#define ANS
int main() {
#ifdef ANS
freopen("kun.in","r",stdin);
freopen("kun.out","w",stdout);
#endif
read(n);
For(i,1,n) read(a[i]);
Rep(i,n,1) {
mx[i]=mx[i+1];
if(a[i]>mx[i]) mx[i]=a[i];
}
For(i,1,n) {
while(top&&sta[top]>mx[i]) {
printf("%d ",sta[top--]);
}
sta[++top]=a[i];
}
while(top) {
printf("%d ",sta[top--]);
}
puts("");
Formylove;
}
静渊以有谋,疏通而知事。