记录编号 60518 评测结果 AAAAAAAAAA
题目名称 [NOI 2010]超级钢琴 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 3.171 s
提交时间 2013-05-26 11:58:15 内存使用 75.82 MiB
显示代码纯文本
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<iomanip>
  4. #include<map>
  5. #include<set>
  6. #include<vector>
  7. #include<cstring>
  8. #include<queue>
  9. #include<deque>
  10. #include<algorithm>
  11. #include<cmath>
  12. using namespace std;
  13. typedef long long ll;
  14. const ll SIZEN=500010;
  15. ll n,k;
  16. ll a[SIZEN]={0};
  17. ll s[SIZEN]={0};
  18. ll f[SIZEN][20]={0};//ST,但里面存的是最大值的位置
  19. ll min(ll a,ll b){
  20. return a<b?a:b;
  21. }
  22. void ST_init(ll a[SIZEN]){
  23. ll m=floor(log((double)n)/log(2.0));
  24. ll i,j;
  25. for(i=1;i<=n;i++) f[i][0]=i;
  26. for(j=1;j<=m;j++){
  27. for(i=1;i<=n;i++){
  28. if(i+(1<<j)-1>n) continue;
  29. f[i][j]=f[i][j-1];
  30. if(a[f[i+(1<<(j-1))][j-1]]>a[f[i][j]]) f[i][j]=f[i+(1<<(j-1))][j-1];
  31. }
  32. }
  33. }
  34. ll rmq(ll l,ll r){//这里返回的是位置
  35. ll m=floor(log((double)(r-l+1))/log(2.0));
  36. if(s[f[l][m]]>s[f[r-(1<<m)+1][m]]) return f[l][m];
  37. else return f[r-(1<<m)+1][m];
  38. }
  39. class NODE{
  40. public:
  41. ll pos;
  42. ll l,r;
  43. ll num;
  44. //这样四个数表示:在左端点为pos,右端点在[l,r]之间的所有和弦的最大值num
  45. ll ind;//最大值的标号
  46. void calc(void){
  47. ind=rmq(l,r);
  48. num=s[ind]-s[pos-1];
  49. }
  50. };
  51. bool operator < (NODE a,NODE b){
  52. return a.num<b.num;
  53. }
  54. priority_queue<NODE> Q;
  55. ll ans=0;
  56. void work(void){
  57. ll i;
  58. NODE x,y,z;
  59. for(i=1;i<=k;i++){
  60. x=Q.top();Q.pop();
  61. ans+=x.num;
  62. y.pos=z.pos=x.pos;
  63. y.l=x.l,z.r=x.r;
  64. y.r=x.ind-1,z.l=x.ind+1;
  65. if(y.r>=y.l){
  66. y.calc();
  67. Q.push(y);
  68. }
  69. if(z.r>=z.l){
  70. z.calc();
  71. Q.push(z);
  72. }
  73. }
  74. }
  75. void init(void){
  76. ll L,R;
  77. scanf("%lld%lld%lld%lld",&n,&k,&L,&R);
  78. ll i;
  79. for(i=1;i<=n;i++){
  80. scanf("%lld",&a[i]),s[i]=s[i-1]+a[i];
  81. }
  82. ST_init(s);
  83. NODE x;
  84. ll lnow,rnow;
  85. for(i=1;i<=n;i++){
  86. if(i+L-1>n) break;
  87. lnow=i+L-1;
  88. rnow=min(i+R-1,n);
  89. x.pos=i,x.l=lnow,x.r=rnow;
  90. x.calc();
  91. Q.push(x);
  92. }
  93. }
  94. int main(){
  95. freopen("piano.in","r",stdin);
  96. freopen("piano.out","w",stdout);
  97. init();
  98. work();
  99. cout<<ans<<endl;
  100. return 0;
  101. }