题解:P17543 [JAG 2026 Summer Camp #2] Deque Bracket Optimization
更好的阅读体验
这个是反悔贪心?是不是不太像,感觉说直接贪是不是更自然。
首先考虑问题的静态情形怎么做。思考一个括号序列什么时候是合法的:当且仅当前 (。然而 (,最后一个位置一定是 ),所以不用考虑。所以我们可以把第一个和最后一个位置去除,在执行完去除操作所剩下的括号序列上,前 (。
那么我们从左往右考虑,维护目前未被确定为 ( 的所有位置(下文称为“未确定集合”)。维护一个变量 ( 的集合,然后直接贪心地从未确定集合中选出
这么做为什么正确?发现,一个决策会影响一个后缀,也就是一个
至此可以解决只有
接下来考虑同时存在 ) 对应位置的 ) 的位置集合,每次取出集合中
然后发现这两个做法可以合并!具体地,我们发现做法 ( 的集合就是目前确定为 ) 的集合,做法 ) 的集合就是目前确定的 ( 的集合,因此这两个集合是互补的!因此假设目前 ( 的集合为 ) 的集合是
至此解决了同时存在
再考虑操作
但是发现,我们可以把上述
至此问题在
#include<bits/stdc++.h>
#define endl '\n'
#define N 400006
using namespace std;
using i64=long long;
int q;
struct DS {
int l,r; i64 sum;
priority_queue<int> rb;
priority_queue<int,vector<int>,greater<int> > lb;
DS():l(-2e9),r(-2e9),sum(0) {}
void push_back(int x,int y)
{
if(l==-2e9)return l=x,r=y,(void)0;
rb.push(r),rb.push(x),r=y;
lb.push(rb.top()),sum+=rb.top(),rb.pop();
}
void push_front(int x,int y)
{
if(l==-2e9)return l=y,r=x,(void)0;
lb.push(l),lb.push(x),sum+=l+x,l=y;
rb.push(lb.top()),sum-=lb.top(),lb.pop();
}
};
void solve()
{
scanf("%d",&q);
DS in,out; deque<int> dq;
for(int i=1,o,x,y;i<=q;i++)
{
scanf("%d%d%d",&o,&x,&y);
if(o==3||o==2&&i==1)
{
out.push_back(x,y);
if(i>1)in.push_back(dq.back(),x);
dq.push_back(x),dq.push_back(y);
} else if(o==1) {
out.push_front(x,y);
if(i>1)in.push_front(dq.front(),x);
dq.push_front(x),dq.push_front(y);
} else {
in.push_front(dq.front(),x),in.push_back(dq.back(),y);
swap(in,out),dq.push_front(x),dq.push_back(y);
}
printf("%lld\n",out.l+out.sum);
}
}
main()
{
int T; scanf("%d",&T);
while(T--)solve();
return 0;
}