题解:CF2026F Bermart Ice Cream
Albert_van · · 题解
题 题。题外话:这场有点水平,E 题让我重拾了最大权闭合子图的记忆。
首先考虑没有这个可持久化(只有
考虑如果把滑动窗口换成栈(要求
回到原问题,暴力可持久化不能接受(修改量总共 pop_back 和 push_front,也就是把上文队列换成双端队列。双栈模拟仍然正确(插入删除都在对应一边,删除时如果那边的栈空了就把另一个栈全倒腾过来),不过复杂度是假的(多次 push_back 然后 pop_front 和 pop_back 交错能卡掉)。
发现每次把整个栈转移过去有点极端了。事实上,每次只转移栈底的
另外一开始把
#include <cstdio>
#include <vector>
#include <stack>
#include <cstring>
using namespace std;
void cmx(int &x,int y){if(x<y) x=y;}
const int W=2327;
int rbq[W];
struct BMI{int p,t;};
void ad(int* f,BMI x){
for(int i=W-1;i>=x.p;--i) cmx(f[i],f[i-x.p]+x.t);
}
namespace DS{
class st{
struct node{BMI x;int f[W];}tmp;
public:stack<node> s;
bool emp(){return s.empty();}
void push(BMI x){
memcpy(tmp.f,s.empty()?rbq:s.top().f,W<<2);
ad(tmp.f,x);tmp.x=x;s.push(tmp);
}
BMI acs_tp(){BMI x=s.top().x;s.pop();return x;}
}l,r,t;
void adj(){
bool flg=r.emp();if(flg) l.s.swap(r.s);
int s=(int)r.s.size()>>1;
while(s--) t.push(r.acs_tp());
while(!r.emp()) l.push(r.acs_tp());
while(!t.emp()) r.push(t.acs_tp());
if(flg) l.s.swap(r.s);
}
int qry(int p){
int *f=l.emp()?rbq:l.s.top().f,*g=r.emp()?rbq:r.s.top().f,res=0;
for(int i=0;i<=p;++i) cmx(res,f[i]+g[p-i]);
return res;
}
BMI acs_frt(){if(l.emp()) adj();return l.acs_tp();}
void pop_bck(){if(r.emp()) adj();r.acs_tp();}
}
const int N=34102;
vector<int> vc[N];
struct qry{int p,i;};
vector<qry> qr[N];
bool del[N],ref[N];BMI w[N];int ans[N];
void dfs(int u){
if(del[u]) w[u]=DS::acs_frt();
if(ref[u]) DS::r.push(w[u]);
for(auto[p,i]:qr[u]) ans[i]=DS::qry(p);
for(int v:vc[u]) dfs(v);
if(ref[u]) DS::pop_bck();
if(del[u]) DS::l.push(w[u]);
}
int cur[N],v;
int main()
{
int q,V=1,qc=0;scanf("%d",&q);
while(q--){int f,x;scanf("%d%d",&f,&x);switch(f){
case 1:vc[cur[x]].push_back(cur[++V]=++v);break;
case 2:vc[cur[x]].push_back(++v),ref[cur[x]=v]=1,scanf("%d%d",&w[v].p,&w[v].t);break;
case 3:vc[cur[x]].push_back(++v),del[cur[x]=v]=1;break;
case 4:int p;scanf("%d",&p);qr[cur[x]].push_back((qry){p,++qc});break;
}}
dfs(0);for(int i=1;i<=qc;++i) printf("%d\n",ans[i]);
}