A. 做任务
思路:由于任务级别只有五个,我们开个桶堆(顾名思义,就是类型是堆的桶)记录下每个任务。输出时从头到尾扫一遍桶,看里面是否有元素。全有的话就输出。
for(int i=1;i<=n;i++)
{
q[a[i]].push(i);
if(q[1].size() && q[2].size() && q[3].size() && q[4].size() && q[5].size())
{
cout<<q[1].top()<<" "<<q[2].top()<<" "<<q[3].top()<<" "<<q[4].top()<<" "<<q[5].top()<<endl;
q[1].pop(),q[2].pop(),q[3].pop(),q[4].pop(),q[5].pop();
}
else cout<<"-1"<<endl;
}
B. 换队伍
思路:这题是真的狗,卡我钥匙值卡了10多次!!!
我们用两个向量模拟队伍,离开队伍时打上钥匙值用来表示。注意钥匙值的取法。
a.push_back(-1),b.push_back(-1);
for(int i=1;i<=n1;i++) a.push_back(i),mp[i]=i;
for(int i=1;i<=n2;i++) b.push_back(i+n1),mp[i+n1]=INF+i;
while(q--)
{
int x; cin>>x;
if(mp[x]<INF) b.push_back(x),mp[x]=INF+b.size()-1;
else a.push_back(x),mp[x]=a.size()-1;
}
for(int i=1;i<a.size();i++) if(mp[a[i]]==i) cout<<a[i]<<" "; cout<<endl;
for(int i=1;i<b.size();i++) if(mp[b[i]]==INF+i) cout<<b[i]<<" "; cout<<endl;
C. 移动撤销
思路:模拟就完事了。全员通过。
D. 果巨记事本
思路:用栈记录下每一次的状态,利用 STL 的substr计算。注意最后一个操作是直接回到之前的操作,并不是把之前的操作 copy 过来。注意是多组数据!!!多组数据!!!多组数据!!!
stack<string> a;
a.push("");
while(T--)
{
int opt; cin>>opt;
if(opt==1)
{
string p; cin>>p;
a.push(a.top()+p);
}
if(opt==2)
{
int l; cin>>l;
string op=a.top();
a.push(op.substr(0,op.length()-l));
}
if(opt==3)
{
int l; cin>>l;
string op=a.top();
cout<<op[l-1]<<endl;
}
if(opt==4)
{
a.pop();
}
E. 矩阵
思路:其实就是P1899的加强版。又是一道全过的题。
F. 校门口外的树
思路:看到“最少要花费多少的时间可以修剪使得树木递增”这几个字了吗?
想到二分了吗?
我们二分答案,设b数组是剪过过后的长,那么有 if(a[i]<b[i-1]+u+1) b[i]=b[i-1]+1; else b[i]=a[i]-u; 特别的, if(a[1]-u<=1) b[1]=1; else b[1]=a[1]-u;。如果在某一棵树上,存在b[i-1]-u>=a[i],就说明当前长度不行。
bool ck(int u)
{
int flag=1;
for(int i=1;i<=n;i++) b[i]=a[i];
if(a[1]-u<=1) b[1]=1;
else b[1]=a[1]-u;
for(int i=2;i<=n;i++)
{
if(b[i-1]-u>=a[i])
{
flag=0;
break;
}
else
{
if(a[i]<b[i-1]+u+1) b[i]=b[i-1]+1;
else b[i]=a[i]-u;
}
}
return flag;
}