【bzoj3747】[POI2015]Kinoman
题解:
水题
从左向右维护以每一个作为右端点的最大值
线段树维护
代码:
#include <bits/stdc++.h> using namespace std; #define rint register ll #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) #define mid ((h+t)>>1) #define ll long long const ll N=1e6+10; const ll N2=N*4; ll a[N],b[N],p1[N],p2[N]; struct sgt{ ll maxa[N2],lazy[N2]; IL void down(rint x) { maxa[x*2]+=lazy[x]; maxa[x*2+1]+=lazy[x]; lazy[x*2]+=lazy[x]; lazy[x*2+1]+=lazy[x]; lazy[x]=0; } #define updata(x) maxa[x]=max(maxa[x*2],maxa[x*2+1]) void change(ll x,ll h,ll t,ll h1,ll t1,ll k) { if (h1<=h&&t<=t1) { lazy[x]+=k; maxa[x]+=k; return; } down(x); if (h1<=mid) change(x*2,h,mid,h1,t1,k); if (mid<t1) change(x*2+1,mid+1,t,h1,t1,k); updata(x); } }S; int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); ll n,m; cin>>n>>m; rep(i,1,n) cin>>a[i]; rep(i,1,m) cin>>b[i]; ll ans=0; rep(i,1,n) { ll x=a[i]; S.change(1,1,n,p1[x]+1,i,b[a[i]]); if (p2[x]+1<=p1[x]) S.change(1,1,n,p2[x]+1,p1[x],-b[a[i]]); ans=max(ans,S.maxa[1]); p2[a[i]]=p1[a[i]]; p1[a[i]]=i; } cout<<ans<<endl; return 0; }