Cookies
Cookies
qoj 难度为 \(8\),很牛的题。
首先对题目进行转化,考虑加入初始糖果 \(k\) 后答案的变化。
我们定义一个变量 \(v = a_k\),接下来从 \(1\) 到 \(m\) 依次处理下标 \(i\):
-
若 \(s_i = \texttt{S}\) 且 \(v > b_i\),则交换 \(v\) 和 \(b_i\)
-
若 \(s_i = \texttt{B}\) 且 \(v < b_i\),则交换 \(v\) 和 \(b_i\)
显然在这套过程过后,\(v\) 就是新留下来的饼干,我们需要求出 \(v\) 的值。
考虑按照 \(s_i\) 将饼干合成连续段,这里以 \(s_i = \texttt{S}\) 为例。
经过若干个 \(\texttt{S}\) 后,桌上剩余的饼干必然会越来越苦。
考虑将这些 \(\texttt{S}\) 合并成一个小根堆,记堆顶为 \(top\),则:
- 若 \(v > top\),则交换 \(v\) 和 \(top\)
对于 \(\texttt{B}\),维护一个大根堆:
- 若 \(v < top\),则交换 \(v\) 和 \(top\)
有如下结论:
- 若存在相邻的 \(\texttt{SB}\),且 \(top_S \geq top_B\),则可以交换这两者。
分类讨论:
-
\(v > top_S\) 时,只会和小根堆交换,显然结果不变,\(v < top_B\) 同理
-
\(top_B \leq v \leq top_S\) 时,两者都不会交换,结果不变
在交换完后,我们仍然可以与旁边的堆进行合并。
我们声称这么做的复杂度是双 \(\log\) 的,我不会证。
#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
using namespace std;
const long long mod=1000000000;
const bool S=false,B=true;
long long a[200010],b[200010];
int m[200010];
priority_queue<int,vector<int>,greater<int> > pq_S[200010];
priority_queue<int,vector<int>,less<int> > pq_B[200010];
bool check_id(int id){
if(!pq_S[id].empty()){
return S;
}
if(!pq_B[id].empty()){
return B;
}
}
stack<int> st;
long long solve(long long v){
stack<int> add_st;
while(!st.empty()){
add_st.push(st.top());
st.pop();
}
while(!add_st.empty()){
int id_now=add_st.top();
add_st.pop();
if(st.empty()){
st.push(id_now);
}
else{
int id_lst=st.top();
st.pop();
bool check_lst=check_id(id_lst),check_now=check_id(id_now);
if(check_lst==S && check_now==S){
if(pq_S[id_lst].size()>pq_S[id_now].size()){
swap(pq_S[id_lst],pq_S[id_now]);
}
while(!pq_S[id_lst].empty()){
pq_S[id_now].push(pq_S[id_lst].top());
pq_S[id_lst].pop();
}
add_st.push(id_now);
}
if(check_lst==S && check_now==B){
if(pq_S[id_lst].top()>=pq_B[id_now].top()){
if(st.empty()){
st.push(id_lst);
st.push(id_now);
}
else{
add_st.push(id_lst);
add_st.push(id_now);
}
}
else{
st.push(id_lst);
st.push(id_now);
}
}
if(check_lst==B && check_now==S){
if(pq_B[id_lst].top()<=pq_S[id_now].top()){
if(st.empty()){
st.push(id_lst);
st.push(id_now);
}
else{
add_st.push(id_lst);
add_st.push(id_now);
}
}
else{
st.push(id_lst);
st.push(id_now);
}
}
if(check_lst==B && check_now==B){
if(pq_B[id_lst].size()>pq_B[id_now].size()){
swap(pq_B[id_lst],pq_B[id_now]);
}
while(!pq_B[id_lst].empty()){
pq_B[id_now].push(pq_B[id_lst].top());
pq_B[id_lst].pop();
}
add_st.push(id_now);
}
}
}
while(!st.empty()){
add_st.push(st.top());
st.pop();
}
while(!add_st.empty()){
int id_now=add_st.top();
add_st.pop();
bool check_now=check_id(id_now);
if(check_now==S){
long long pre=pq_S[id_now].top();
pq_S[id_now].pop();
if(v>pre){
swap(v,pre);
}
pq_S[id_now].push(pre);
}
if(check_now==B){
long long pre=pq_B[id_now].top();
pq_B[id_now].pop();
if(v<pre){
swap(v,pre);
}
pq_B[id_now].push(pre);
}
st.push(id_now);
}
return v;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
int m;
scanf("%d",&m);
for(int i=1;i<=n;i++){
scanf("%lld",&b[i]);
}
for(int i=1;i<=m;i++){
char ch;
cin>>ch;
if(ch=='S'){
pq_S[i].push(b[i]);
}
if(ch=='B'){
pq_B[i].push(b[i]);
}
st.push(i);
}
long long last_ans=0;
for(int i=1;i<=n;i++){
a[i]=(a[i]+last_ans)%mod;
last_ans+=solve(a[i]);
printf("%lld ",last_ans);
}
return 0;
}

浙公网安备 33010602011771号