[NOI2010] Super piano (+ ST heap table)

The meaning of problems

Given a sequence of length n, find k consecutive intervals, and such that the maximum length of the interval between [l, r].

To 100% of the data, -1000 ≤ Ai ≤ 1000, n, k <= 500000.

answer

First greedy: certainly the largest k selected intervals, intervals and can deal with the prefix and the question is how to find out if the violence is to join, then will reach $ n ^ {2} $.

So the emergence of a fairy :

Consider the left fixing point i, and the interval is [k] -sum [i] sum, to the maximum and, for as long as sum [k] maximum, k has a legal range, the initial point when the right to find the left point for each legitimate one of the largest pile into the interval. Then, when selecting the k intervals, the top of the stack when taken out, the valid range of the right end divided into two parts, and then into the reactor. This ensures'll always find these k intervals, because he always has the left end point (funny), at the time of the split point range on the right end of the interval to ensure the same point could be left to the election. Will select up each split into two and then into the reactor, so that a maximum number into n + 2k.

So consider how to find the largest sum [k], just like the biggest query section, segment tree can, but need not be amended if ST table looks a bit better.

The element is placed in the stack definition of the structure, including the left point, right point range and optimum right point.

 

#include <bits / STDC ++ H.>
 the using  namespace STD; 

#define LL Long Long
 const  int MAXN = 500 005 ;
 int n-, K, L, R & lt; 
LL A [MAXN], SUM [MAXN]; 
int ST [MAXN] [ 25 ], LG [MAXN]; // local maximum value of the 
struct CX {
   int start, L, R & lt, End; // interval begins, the right end of the range, takes place in the right most point value 
  CX ( int start, int L, int R & lt, int End): Start (Start), L (L), R & lt (R & lt), End (End) {} 
  Friend BOOL  operator <( const CX & A,const cx &b){return sum[a.end]-sum[a.start-1]<sum[b.end]-sum[b.start-1];}
};

priority_queue<cx> q;

template<class T>inline void read(T &x){
  x=0;int f=0;char ch=getchar();
  while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
  while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  x= f ? -x : x;
}

void RMQ(){
  for(int i=1;i<=n;i++) st[i][0]=i;
  for(int j=1;(1<<j)<=n;j++)
   for(int i=1;i+(1<<j)-1<=n;i++){
     int x=st[i][j-1],y=st[i+(1<<(j-1))][j-1];
     st[i][j]= sum[x]>sum[y] ? x : y;
   }
}

int query(int l,int r){
  int o=lg[r-l+1],x=st[l][o],y=st[r-(1<<o)+1][o];
  //printf("%d %d %d %d %d %d\n",l,r,o,1<<o,x,y);
  return sum[x]>sum[y] ? x : y;
}

int main(){
  //freopen("testdata.in","r",stdin);
  read(n);read(k);read(L);read(R);
  lg[0]=-1;
  for(int i=1;i<=n;i++)
   lg[i]=lg[i>>1]+1;
  //for(int i=1;i<=n;i++) printf("%d ",lg[i]);
  for(int i=1;i<=n;i++){
    read(a[i]);
    sum[i]=sum[i-1]+a[i];
  }
  RMQ();
  for(int i=1;i+L-1<=n;i++){
    int l=i+L-1,r=min(i+R-1,n),x=query(l,r);
    //printf("%d %d %d %d \n",i,l,r,x);
    q.push(cx(i,l,r,x));
  }

  ll ans=0;
  for(int i=1;i<=k;i++){
    cx get=q.top();
    q.pop();
    ans+=sum[get.end]-sum[get.start-1];
    //printf("%d %d\n",get.start,get.end);
    if(get.end!=get.l) q.push(cx(get.start,get.l,get.end-1,query(get.l,get.end-1)));
    if(get.end!=get.r) q.push(cx(get.start,get.end+1,get.r,query(get.end+1,get.r)));
  }
  printf("%lld",ans);
}
View Code

 

Guess you like

Origin www.cnblogs.com/sto324/p/11291497.html