bzoj3747Kinoman[POI2015](线段树)

Posted QuartZ_Z

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3747Kinoman[POI2015](线段树)相关的知识,希望对你有一定的参考价值。

  题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3747

  对于这种题,考虑固定区间的右端点为r,设区间左端点为l能取得的好看值总和为a[l],那么就相当于当r取不同取值时所有al的最大值。

  设last[i]表示第i部电影上一次出现的位置,当右端点r右移1位时,因为只有看了一遍的电影能获取好看值,所以能取得f[r]的好看值的al只能是在last[r]~r这个区间。因此每次右移时,last[last[r]]+1~last[r]减去w[f[r]],last[r]+1~r加上w[f[r]]。

  具体实现, 就是维护一个资瓷区间加与查询区间最大的线段树。

  代码(常数真大):

技术分享图片
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#define ll long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define inf 1ll<<60
ll read()
{
    ll tmp=0; char c=getchar(),f=1;
    for(;c<0||9<c;c=getchar())if(c==-)f=-1;
    for(;0<=c&&c<=9;c=getchar())tmp=tmp*10+c-0;
    return tmp*f;
}
using namespace std;
struct point{
    ll delta,mx;
}a[4000010];
ll w[1000010];
int f[1000010],last[1000010],pos[1000010];
int n,m;
void add(int now,int l,int r,int x,int y,ll k)
{
    if(x<=l&&r<=y){
        a[now].delta+=k; a[now].mx+=k;
    }
    else{
        int mid=(l+r)>>1;
        if(x<=mid)add(now<<1,l,mid,x,y,k);
        if(mid<y)add(now<<1|1,mid+1,r,x,y,k);
        a[now].mx=max(a[now<<1].mx,a[now<<1|1].mx)+a[now].delta; 
    }
}
ll getmax(int now,int l,int r,int x,int y)
{
    if(x<=l&&r<=y)return a[now].mx;
    else{
        ll tmp=-inf; int mid=(l+r)>>1;
        if(x<=mid)tmp=max(tmp,getmax(now<<1,l,mid,x,y));
        if(mid<y)tmp=max(tmp,getmax(now<<1|1,mid+1,r,x,y));
        return tmp+a[now].delta;
    }
}
int main()
{
    int i;
    n=read(); m=read();
    last[0]=-1;
    for(i=1;i<=n;i++){
        f[i]=read();
        if(!pos[f[i]])last[i]=0;
        else last[i]=pos[f[i]];
        pos[f[i]]=i;
    }
    for(i=1;i<=m;i++)w[i]=read();
    ll ans=-inf;
    for(i=1;i<=n;i++){
        add(1,1,n,last[i]+1,i,w[f[i]]);
        if(~last[last[i]])add(1,1,n,last[last[i]]+1,last[i],-w[f[i]]);
        ans=max(ans,getmax(1,1,n,1,i));
    }
    printf("%lld\n",ans);
}
bzoj3747

 

以上是关于bzoj3747Kinoman[POI2015](线段树)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3747: [POI2015]Kinoman

bzoj3747[POI2015]Kinoman

@bzoj - 3747@ [POI2015] Kinoman

BZOJ3747[POI2015]Kinoman 线段树

bzoj3747: [POI2015]Kinoman

[bzoj3747][POI2015]Kinoman_线段树