小目标:高考假以内,做完POI2015
和POI2014的一半
怎么搞?
实际套路也挺简单的。
你看:l,r。这是n*n的算法
一般来说1e6 怎么搞是On *✧⁺˚⁺ପ(๑・ω・)੭ु⁾⁾
但是Onlogn 却必须得跑过
原因是一般来说解决是枚举一个l 或者是中位数。
但是必须得log 那么毒瘤卡常数
你用一个后向星记录一个 Pre即上一个为Wi 和 Last
然后区间更新 Pre i +1 ,i +Wi
Pre(pre)+1 ,Pre i -Wi
然后查询到l位置最大值
#include<bits/stdc++.h>
using namespace std;
typedef int INT;
#define int long long
const int N=1e6+100;
inline void read(int &x){
x=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
struct Max_query{
#define lc (p<<1)
#define rc (p<<1|1)
struct Segment_Tree{
int lson,rson,sum;
int addlazy;
}T[N<<2];
void build(int p,int l,int r){
T[p].lson=l;
T[p].rson=r;
if(l==r){
T[p].sum=0;
return;
}
int mid=(l+r)/2;
build(lc,l,mid);
build(rc,mid+1,r);
}
inline void pushup(int p){
T[p].sum=max(T[lc].sum,T[rc].sum);
}
inline void pushdown(int p){
if(T[p].addlazy){
T[lc].sum+=T[p].addlazy;
T[rc].sum+=T[p].addlazy;
T[lc].addlazy+=T[p].addlazy;
T[rc].addlazy+=T[p].addlazy;
T[p].addlazy=0;
}
}
inline void update(int p,int l,int r,int val){
if(l<=T[p].lson&&T[p].rson<=r){
T[p].sum+=val;
T[p].addlazy+=val;
return;
}
int mid=(T[p].lson+T[p].rson)/2;
pushdown(p);
if(l<=mid) update(lc,l,r,val);
if(mid<r ) update(rc,l,r,val);
pushup(p);
}
inline int query(int p,int l,int r){
int ret=-1;
if(l<=T[p].lson&&T[p].rson<=r){
return T[p].sum;
}
pushdown(p);
int mid=(T[p].lson+T[p].rson)/2;
if(l<=mid) ret=max(ret,query(lc,l,r));
if(mid<r ) ret=max(ret,query(rc,l,r));
return ret;
}
}T;
int pre[N]={};
int last[N]={};
int A[N]={};
int W[N]={};
int n,m;
INT main(){
read(n);
// cout<<n;
read(m);
for(int i=1;i<=n;i++){
read(A[i]);
pre[i]=last[A[i]];
last[A[i]]=i;
}
for(int i=1;i<=m;i++){
read(W[i]);
}
T.build(1,1,n);
int ans=-1;
for(int i=1;i<=n;i++){
T.update(1,pre[i]+1,i,W[A[i]]);
if(pre[i]!=0)
T.update(1,pre[pre[i]]+1,pre[i],-W[A[i]]);
ans=max(ans,T.query(1,1,i));
// cout<<ans<<'\n';
}
cout<<ans;
}