P11727 [JOIG 2025] 神経衰弱 2 / Pair Matching 2 题解
Drink_Assam · · 题解
线段树优化 DP。
观察可发现,海狸比太郎每次拿起一张牌,左手的牌必然会丢掉。考虑 DP,设
对于第一次出现的牌
对于第二次出现的牌
如果有必要拿一张其他牌,那么它必然能加分,并且它的上一次出现在
前两种转移都好做,最后一种线段树优化。因为转移是按照
:::info[代码]
#include <iostream>
#include <queue>
using namespace std;
using ll= long long;
const int N=800005;
ll val[N<<2],tag[N<<2];
void app(int u,ll x) {
val[u]=max(val[u],x);
tag[u]=max(tag[u],x);
}
void pushup(int u) {
val[u]=max(val[u<<1],val[u<<1|1]);
}
void pushdown(int u) {
if(tag[u]) {
app(u<<1,tag[u]);
app(u<<1|1,tag[u]);
tag[u]=0;
}
}
void upd(int u,int l,int r,int s,int t,ll x) {
if(s<=l&&r<=t) {
app(u,x);
return;
}
pushdown(u);
int mid=(l+r)>>1;
if(s<=mid) upd(u<<1,l,mid,s,t,x);
if(t>mid) upd(u<<1|1,mid+1,r,s,t,x);
pushup(u);
}
ll query(int u,int l,int r,int s) {
if(l==r) return val[u];
pushdown(u);
int mid=(l+r)>>1;
if(s<=mid) return query(u<<1,l,mid,s);
else return query(u<<1|1,mid+1,r,s);
}
priority_queue<pair<int,pair<int,ll> > > pq;
int n,a[N],pos[N];
void upd(int l,int r,ll w) {
pq.emplace(-r,make_pair(l,w));
}
void upd(int x) {
while(pq.size()) {
int l=pq.top().second.first,r=-pq.top().first;
if(r>=x) return;
upd(1,1,n+n,l,r,pq.top().second.second);
pq.pop();
}
}
ll v[N],dp[N],c[N],mx[N];
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n+n;i++) {
cin>>a[i];
pos[a[i]]^=i;
}
for(int i=1;i<=n;i++)
cin>>v[i];
for(int i=1;i<=n+n;i++) {
dp[i]=dp[i-1];
int o=pos[a[i]]^i;
upd(i);
if(o>i) {
if(i+1<o)
upd(i+1,o-1,dp[i]+v[a[i]]);
continue;
}
dp[i]=max(dp[i],query(1,1,n+n,o)+v[a[i]]);
dp[i]=max(dp[i],dp[o-1]+v[a[i]]);
}
cout<<dp[n+n];
return 0;
}
:::
其实我的方法复杂了,不用堆,不要枚举