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

    无关:突然感觉之前的码风调代码不太方便,还是稍微改一下吧,毕竟现在竞赛的代码写出来还是要给自己看的...


    这道题,显然确定了一个端点之后这个端点对应的区间和的最大值是定的,很容易想到用ST表维护一个前缀和最大值

    然后再维护一个大根堆,记录每个合法最大值区间

    在每一个状态时,堆顶元素一定是最优解,所以每次取堆顶元素即可

    但是把堆顶元素取出来之后,之后最优解还有可能在当前堆顶的集合中的子集里产生,所以还需要把当前堆顶有可能产生的其他贡献丢到堆里

    设堆顶元素在位置pos处取到最优解的情况,那么因为两个和弦不能相同,可能的新的贡献的右端点只有可能在$[l,pos-1]$和$[pos+1,r]$中取到

    把这两个区间也丢进去维护就好了

     1 //hgs AK IOI,IMO,ICHO,IPHO
     2 #include<bits/stdc++.h>
     3 #define int long long
     4 #define writeln(x)  write(x),puts("")
     5 #define writep(x)   write(x),putchar(' ')
     6 using namespace std;
     7 inline int read(){
     8     int ans=0,f=1;char chr=getchar();
     9     while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();}
    10     while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
    11     return ans*f;
    12 }void write(int x){
    13     if(x<0) putchar('-'),x=-x;
    14     if(x>9) write(x/10);
    15     putchar(x%10+'0');
    16 }const int M = 5E5+5;
    17 int a[M],s[M],st[M][21],n,m,sl,sr,lg2[M]={-1},bin[21]={1};
    18 inline int max(int x,int y){return ((x>y)?(x):(y));}
    19 inline int min(int x,int y){return ((x>y)?(y):(x));}
    20 inline int chkmax(int x,int y){return (s[x]>s[y])?(x):(y);}
    21 inline void Pre()
    22 {
    23     for(int i=1;i<=20;i++)
    24         bin[i]=bin[i-1]<<1;
    25     for(int i=1;i<=n;i++)
    26         lg2[i]=lg2[i>>1]+1,
    27         st[i][0]=i;
    28     for(int j=1;j<=20;j++)
    29         for(int i=1;i+bin[j]-1<=n;i++)
    30             st[i][j]=chkmax(st[i][j-1],st[i+bin[j-1]][j-1]);
    31 }
    32 inline int Query(int l,int r)
    33 {
    34     return chkmax(st[l][lg2[r-l+1]],st[r-bin[lg2[r-l+1]]+1][lg2[r-l+1]]);
    35 }
    36 struct P
    37 {
    38     int x,l,r;
    39     inline int Calc()const
    40     {
    41         return s[Query(l,r)]-s[x-1];
    42     }
    43     friend bool operator<(const P&a,const P&b)
    44     {
    45         return a.Calc()<b.Calc();
    46     }
    47 };
    48 priority_queue<P>q;
    49 inline P Make(int x,int l,int r)
    50 {
    51     r=min(r,n);
    52     return (P){x,l,r};
    53 }
    54 inline void Split(const P&x)
    55 {
    56     P t1,t2;
    57     int pos=Query(x.l,x.r);
    58     if(x.l!=pos)q.push(Make(x.x,x.l,pos-1));
    59     if(x.r!=pos)q.push(Make(x.x,pos+1,x.r));
    60 }
    61 signed main()
    62 {
    63     n=read(),m=read(),sl=read(),sr=read();
    64     for(int i=1,x;i<=n;i++)
    65         s[i]=read(),s[i]+=s[i-1];
    66     Pre();
    67     for(int i=1;i+sl-1<=n;i++)
    68         q.push(Make(i,i+sl-1,i+sr-1));
    69     register int ans(0);
    70     while(m--)
    71     {    
    72         P now=q.top();
    73         q.pop();
    74         ans+=now.Calc();
    75         Split(now);
    76     }cout<<ans;
    77     return 0;
    78 }
  • 相关阅读:
    MTK手机默认音量大小调节工具
    问题:MTK手机软件开发平台中字串资源添加进去了,菜单也能用,但是菜单上的字符串显示不出来。
    GNU ARM汇编快速入门
    想成为嵌入式程序员应知道的0x10个基本问题
    学习MTK需要的环境,平台,资料
    BSP 概念解析
    作为程序员的苦恼
    浅谈程序员的职业规划
    入行三年回顾
    程序员谈“应用推广”
  • 原文地址:https://www.cnblogs.com/zhenglw/p/11773831.html
Copyright © 2011-2022 走看看