【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;
}

 

posted @ 2018-09-25 00:14  尹吴潇  阅读(151)  评论(0编辑  收藏  举报