Given a sequence, find the sequence of K lengths between [L, R] to maximize the sum.
Violent O (N ^ 2 logn), certainly cannot pass
I saw otz for the first afternoon... After studying the problem of others for a long time, I realized what was going on... Sorry, I really cannot understand the idea of the great gods. 0.0
First, maintain the prefix and, the sum [I]-min {sum [J]} (I-r <= j <= I-l)
Then we maintain a large root heap. Every time we take an element ending with I, we add sum [I]-2 thmin {sum [J]}, add sum [I]-3 thmin {sum [J]} after removing this element, and so on.
The maintenance interval is k-small. Divide the tree. If you don't know what it is, the Division tree of NIMA Ben still writes down 0.0.
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define M 500500using namespace std;typedef pair<int,int> abcd;typedef long long ll;int n,k,l,r;ll ans;int sum[M],a[M],b[M],c[M],s[22][M],now[M];abcd heap[M];int top;void insert(abcd x){heap[++top]=x;int t=top;while(t>1&&heap[t]>heap[t>>1])swap(heap[t],heap[t>>1]),t>>=1;}void pop(){heap[1]=heap[top--];int t=2;while(t<=top){if(t<top&&heap[t+1]>heap[t])t++;if(heap[t]>heap[t>>1])swap(heap[t],heap[t>>1]),t<<=1;elsebreak;}}void Build_Tree(int l,int r,int dpt){int i,mid=l+r>>1;int l1=l,l2=mid+1;int left=mid-l+1;if(l==r)return ;for(i=l;i<=r;i++)left-=a[i]<c[mid];for(i=l;i<=r;i++){if(a[i]<c[mid]||a[i]==c[mid]&&left)b[l1++]=a[i],s[dpt][i]=i==l?1:s[dpt][i-1]+1,left-=a[i]==c[mid];elseb[l2++]=a[i],s[dpt][i]=i==l?0:s[dpt][i-1];}memcpy(a+l,b+l,r-l+1<<2);Build_Tree(l,mid,dpt+1);Build_Tree(mid+1,r,dpt+1);}int Get_Ans(int l,int r,int dpt,int x,int y,int k){int mid=l+r>>1;int l1=x==l?0:s[dpt][x-1],l2=s[dpt][y];if(l==r)return c[mid];if(k<=l2-l1)return Get_Ans(l,mid,dpt+1,l+l1,l+l2-1,k);elsereturn Get_Ans(mid+1,r,dpt+1,(mid+1)+(x-l-l1),(mid+1)+(y-l+1-l2)-1,k-l2+l1);}int main(){//freopen("piano.in","r",stdin);//freopen("piano.out","w",stdout);int i;cin>>n>>k>>l>>r;for(i=1;i<=n;i++)scanf("%d",&sum[i]),sum[i]+=sum[i-1];memcpy(a,sum,n+1<<2);memcpy(c,sum,n+1<<2);sort(c,c+n+1);Build_Tree(0,n,0);for(i=l;i<=n;i++){now[i]=1;int temp=Get_Ans(0,n,0,max(i-r,0),i-l,1);insert( make_pair(sum[i]-temp,i) );}for(i=1;i<=k;i++){abcd temp=heap[1];pop();if( now[temp.second]!=(temp.second-l)-( max(temp.second-r,0) )+1 )insert( make_pair(sum[temp.second]-Get_Ans(0,n,0,max(temp.second-r,0),temp.second-l,++now[temp.second]),temp.second) );ans+=temp.first;}cout<<ans<<endl;}
Bzoj 2006 noi2010 super piano tree division + heap