zoukankan      html  css  js  c++  java
  • bzoj3747 [POI2015]Kinoman

    传送门

    分析

    我们首先要记录一个pre[x]表示上一个颜色和x相同的位置。然后我们枚举所有区间的右端点。我们发现对于每一个新的端点x,会导致pre[pre[x]]+1到pre[x]这一段区间的值减w[col[x]],导致pre[x]+1到x这一段区间的值加w[col[x]]。所以我们只需要维护这些信息并每次统计[1,x]区间的最大值就可以了。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    long long w[1001000],col[1001000],d[4400000],head[1001000];
    long long pre[1001000],laz[4400000];
    inline void build(long long le,long long ri,long long wh,long long x,long long y,long long k){
          if(x>y)return;
          if(le>=x&&ri<=y){
              d[wh]+=k;
              laz[wh]+=k;
              return;
          }
          long long mid=(le+ri)>>1;
          if(laz[wh]){
              laz[wh<<1]+=laz[wh];
              laz[wh<<1|1]+=laz[wh];
              d[wh<<1]+=laz[wh];
              d[wh<<1|1]+=laz[wh];
              laz[wh]=0;
          }
          if(mid>=x)build(le,mid,wh<<1,x,y,k);
          if(mid<y)build(mid+1,ri,wh<<1|1,x,y,k);
          d[wh]=max(d[wh<<1],d[wh<<1|1]);
    }
    inline long long q(long long le,long long ri,long long wh,long long x,long long y){
          if(x>y)return 0;
          if(le>=x&&ri<=y){
              return d[wh];
          }
          long long mid=(le+ri)>>1,ans=0;
          if(laz[wh]){
              laz[wh<<1]+=laz[wh];
              laz[wh<<1|1]+=laz[wh];
              d[wh<<1]+=laz[wh];
              d[wh<<1|1]+=laz[wh];
              laz[wh]=0;
          }
          if(mid>=x)ans=max(ans,q(le,mid,wh<<1,x,y));
          if(mid<y)ans=max(ans,q(mid+1,ri,wh<<1|1,x,y));
          d[wh]=ans;
          return ans;
    }
    int main(){
          long long n,m,i,j,k;
          scanf("%lld%lld",&n,&m);
          for(i=1;i<=n;i++)scanf("%lld",&col[i]);
          for(i=1;i<=m;i++)scanf("%lld",&w[i]);
          for(i=1;i<=n;i++){
              pre[i]=head[col[i]];
              head[col[i]]=i;
          }
          long long ans=0;
          for(i=1;i<=n;i++){
              build(1,n,1,pre[pre[i]]+1,pre[i],-w[col[i]]);
              build(1,n,1,pre[i]+1,i,w[col[i]]);
              ans=max(ans,q(1,n,1,1,i));
          }
          printf("%lld
    ",ans);
          return 0;
    }
  • 相关阅读:
    vbs获取当月的第一天和最后一天的日期
    vbscript基础篇
    win10专业版激活
    python selenium中Excel数据维护
    python里面的xlrd模块详解
    python 转换为json时候 汉字编码问题
    用VBA得到EXCEL表格中的行数和列数
    表关联关系,表的复制
    存储引擎,详细建表语句,数据类型,约束
    数据库基础
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9496244.html
Copyright © 2011-2022 走看看