[POI2015]KIN (線段樹)
阿新 • • 發佈:2018-10-04
return 得到 main har https 全局 while 上一個 char
題目鏈接
Solution
線段樹.
觀察題目可以得到一個小 \(trick\) :
對於任意一個節點 \(i\) ,那麽和它顏色相同的上一個節點 \(pre[i]\),肯定不會放在一個區間.
於是考慮對於每一個節點計算它可以獻出貢獻的區間.
先 \(O(n)\) 掃出每一個點的 \(pre\) .
然後從左往右,一次將節點可以貢獻的範圍即 \([pre_i~,~nxt_i)\).
同時將同顏色的上一個節點貢獻刪除.
然後線段樹統計全局最大值即可.
Code
#include<bits/stdc++.h> #define N 1000008 #define ll long long #define mid (l+r>>1) #define in(x) x=read() using namespace std; int read() { char ch=getchar(); int w=0; while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();} return w; } ll pre[N],sgx[N*4],n,k,lazy[N*4]; ll col[N],w[N],lst[N],ans; void push_down(int node) { if(!lazy[node])return; lazy[node<<1]+=lazy[node]; lazy[node<<1|1]+=lazy[node]; sgx[node<<1|1]+=lazy[node]; sgx[node<<1]+=lazy[node]; lazy[node]=0; } void change(int node,int l,int r,int L,int R,int v) { if(l>R||r<L)return; if(l>=L&&r<=R){lazy[node]+=v;sgx[node]+=v;return;} push_down(node); change(node<<1,l,mid,L,R,v); change(node<<1|1,mid+1,r,L,R,v); sgx[node]=max(sgx[node<<1],sgx[node<<1|1]); return; } int main() { in(n),in(k); for(int i=1;i<=n;i++){ in(col[i]); pre[i]=lst[col[i]]; lst[col[i]]=i; } for(int i=1;i<=k;i++)in(w[i]); for(int i=1;i<=n;i++){ change(1,1,n,pre[i]+1,i,w[col[i]]); change(1,1,n,pre[pre[i]]+1,pre[i],-w[col[i]]); ans=max(ans,sgx[1]); } cout<<ans<<endl; }
[POI2015]KIN (線段樹)