zoukankan      html  css  js  c++  java
  • NOI2010 超级钢琴

    http://www.lydsy.com/JudgeOnline/problem.php?id=2006

    静态区间第K大。

    先求A的前缀和sum[i],区间[l,r]其实就是sum[r]-sum[l-1]。

    对于确定的r,要想sum[r]-sum[l-1]最大,就是要sum[l-1]最小。

    对于一个确定的右端点r,其左端点满足r-R+1<=l<=r-L+1。

    那么以r为右端点的长度在L到R之间的区间的最大值为sum[r]-sum[r-R...r-L]中最小值,第二大值为sum[r]-sum[r-R...r-L]中的第二小值......第K大值就是sum[r]-sum[r-R...r-L]的第K小值。

    所以变成询问区间sum[r-R...r-L]中的第K大值。

    我们用可持久化线段树维护。

    首先从1到N枚举r,求出以r为右端点的长度在L到R之间的区间的最大值,然后将这N个最大值放在一个优先队列里。

    然后取出优先队列的最大值区间,记这个区间的右端点为r,求出求出以r为右端点的长度在L到R之间的区间的第二大值,再放到优先队列中。

    这样做K次就行了。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<functional>
    #include<deque>
    #include<cctype>
    #include<climits>
    #include<complex>
    //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
     
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    typedef pair<int,int> PII;
    typedef complex<DB> CP;
    
    #define mmst(a,v) memset(a,v,sizeof(a))
    #define mmcy(a,b) memcpy(a,b,sizeof(a))
    #define re(i,a,b)  for(i=a;i<=b;i++)
    #define red(i,a,b) for(i=a;i>=b;i--)
    #define fi first
    #define se second
    #define m_p(a,b) make_pair(a,b)
    #define SF scanf
    #define PF printf
    #define two(k) (1<<(k))
    
    template<class T>inline T sqr(T x){return x*x;}
    template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
    template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}
    
    const DB EPS=1e-9;
    inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
    const DB Pi=acos(-1.0);
    
    inline int gint()
      {
            int res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    inline LL gll()
      {
          LL res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    
    const int maxN=500000;
    const int maxK=500000;
    
    int N,K,L,R;
    int A[maxN+100];
    LL sum[maxN+100];
    LL ans;
    
    int cnt;
    LL bak[maxN+100];
    
    struct Ttree
     {
       int l,r,sum;
       inline Ttree(){l=r=sum=0;}
    }tree[13000000];
    int MID=0;
    int root[maxN+100];
    inline int New_Node(){tree[++MID]=Ttree();return MID;}
    inline void up(int rt){tree[rt].sum=tree[tree[rt].l].sum+tree[tree[rt].r].sum;}
    inline void update(int &rt,int pastrt,int l,int r,int x)
      {
          if(l>r || x<l || r<x) return;
          if(rt==0)rt=New_Node();
          if(x<=l && r<=x){tree[rt].sum=tree[pastrt].sum+1;return;}
          int mid=(l+r)/2;
          if(x<=mid)
            {
                if(tree[rt].r==0) tree[rt].r=tree[pastrt].r;
                update(tree[rt].l,tree[pastrt].l,l,mid,x);
            }
          else
            {
                if(tree[rt].l==0) tree[rt].l=tree[pastrt].l;
                update(tree[rt].r,tree[pastrt].r,mid+1,r,x);
            }
          up(rt);
      }
    inline int lsum(int rt){return tree[tree[rt].l].sum;}
    inline LL ask(int x,int y,int k)
      {
          int l=1,r=cnt,rt1=(x==0)?0:root[x-1],rt2=root[y];
          while(l!=r)
            { 
              int lge=lsum(rt2)-lsum(rt1),mid=(l+r)/2;
              if(k<=lge)
                      {r=mid;rt1=tree[rt1].l;rt2=tree[rt2].l;}
                    else
                      {l=mid+1;k-=lge;rt1=tree[rt1].r;rt2=tree[rt2].r;}
            }
            return bak[l];
        }
    
    
    inline void build()
      {
          int i;
          cnt=0;
          re(i,0,N)bak[++cnt]=sum[i];
          sort(bak+1,bak+cnt+1);
          cnt=unique(bak+1,bak+cnt+1)-bak-1;
          re(i,0,N)sum[i]=lower_bound(bak+1,bak+cnt+1,sum[i])-bak;
          root[0]=New_Node();
          update(root[0],0,1,cnt,sum[0]);
          re(i,1,N)
            {
                root[i]=New_Node();
                update(root[i],root[i-1],1,cnt,sum[i]);
            }
      }
    
    int l[maxN+100],r[maxN+100],h[maxN+100];
    
    struct Tdata
      {
          int pos;LL v;
          inline Tdata(int _pos=0,LL _v=0){pos=_pos;v=_v;}
        };
    struct cmp{inline bool operator ()(Tdata a,Tdata b){return a.v<b.v;}};
    priority_queue<Tdata,vector<Tdata>,cmp>Q;
    
    int main()
      {
          freopen("piano.in","r",stdin);
          freopen("piano.out","w",stdout);
          int i;
          N=gint();K=gint();L=gint();R=gint();
          re(i,1,N)A[i]=gint();
          re(i,1,N)sum[i]=sum[i-1]+LL(A[i]);
          build();
          re(i,1,N)
              {
                  l[i]=max(0,i-R);
                    r[i]=i-L;
                    h[i]=0;
                    if(l[i]<=r[i] && h[i]+1<=r[i]-l[i]+1)
                      Q.push(Tdata(i,bak[sum[i]]-ask(l[i],r[i],++h[i])));
                }
            while(K--)
              {
                  int pos=Q.top().pos,v=Q.top().v;Q.pop();
                  ans+=v;
                  if(l[pos]<=r[pos] && h[pos]+1<=r[pos]-l[pos]+1)
                      Q.push(Tdata(pos,bak[sum[pos]]-ask(l[pos],r[pos],++h[pos])));
              }
            cout<<ans<<endl;
            return 0;
        }
    View Code
  • 相关阅读:
    3D Computer Grapihcs Using OpenGL
    转:认识MyBean
    转:MyBean的安装
    转:MyBean简介
    Delphi常用关键字用法详解
    红鱼儿
    uniGUI-shuiying
    转:RTC搭建android下三层应用程序访问服务器MsSql-客户端
    转:RTC搭建android下三层应用程序访问服务器MsSql-服务器端
    转(Delphi 新窑洞):使用delphi 开发多层应用(十七)使用RTC web 服务器返回JSON
  • 原文地址:https://www.cnblogs.com/maijing/p/4704930.html
Copyright © 2011-2022 走看看