1 条题解
-
0
首先原题可以转化为最大化 的和,其中 。
然后我们注意到题目给的是单点修改,所以我们可以考虑线段树分治。
用一棵线段树可以轻易维护加操作和删操作。
时间复杂度为 。
代码好写。
#include<bits/stdc++.h> using namespace std; inline int read(){ int x=0;bool f=0;char ch=getchar(); while(ch<'0'||ch>'9')f^=(ch=='-'),ch=getchar(); while('0'<=ch&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x; } const int Maxn=1e6+5; int n,k,q; int a[Maxn]; struct tree{ int t[Maxn<<2]; void change(int x,int l,int r,int d,int p){ if(l==r)return void(t[x]=p); int mid=l+r>>1; if(mid>=d)change(x<<1,l,mid,d,p); else change(x<<1|1,mid+1,r,d,p); t[x]=max(t[x<<1],t[x<<1|1]); } int query(int x,int l,int r,int L,int R){ if(L<=l&&r<=R)return t[x]; int mid=l+r>>1,res=0; if(mid>=L)res=query(x<<1,l,mid,L,R); if(mid<R)res=max(res,query(x<<1|1,mid+1,r,L,R)); return res; } }A; struct node{ int id,val; }; vector<node>t[Maxn<<2]; void change(int x,int l,int r,int L,int R,node g){ if(L>R)return; if(L<=l&&r<=R)return void(t[x].push_back(g)); int mid=l+r>>1; if(mid>=L)change(x<<1,l,mid,L,R,g); if(mid<R)change(x<<1|1,mid+1,r,L,R,g); } int last[Maxn]; stack<node>stk; void dfs(int x,int l,int r,int ans){ int siz=stk.size(); for(node i:t[x]){ int id=i.id; int val=A.query(1,1,n,id,id); A.change(1,1,n,id,0); ans=max(ans,A.query(1,1,n,max(1,id-k+1),min(n,id+k-1))+i.val); A.change(1,1,n,id,i.val); stk.push({id,val}); } if(l==r){ printf("%d\n",ans); } else{ int mid=l+r>>1; dfs(x<<1,l,mid,ans); dfs(x<<1|1,mid+1,r,ans); } while(stk.size()>siz){ A.change(1,1,n,stk.top().id,stk.top().val); stk.pop(); } } int main(){ // freopen(".in","r",stdin); // freopen(".out","w",stdout); n=read();k=read();q=read()+1; for(int i=1;i<=n;i++)a[i]=read(),last[i]=1; for(int i=2;i<=q;i++){ int id=read(),val=read(); change(1,1,q,last[id],i-1,(node){id,a[id]}); a[id]=val;last[id]=i; } for(int i=1;i<=n;i++)change(1,1,q,last[i],q,(node){i,a[i]}); dfs(1,1,q,0); return 0; }
- 1
信息
- ID
- 10645
- 时间
- 8000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者