【BZOJ2482】【SPOJ1557】GSS2

离线处理+线段树即可。

离线,将所有询问按右端点从小到大排序,从小到大枚举答案区间的右端点 i ,维护 sum[j] 表示 [j,i] 中不同值的和,每次把 sum[lst[i]+1..i] 加上 a[i] ,不难发现询问 [l,i] 的答案是 sum[l..i] 中所有元素的历史最大值的最大值。

于是问题就变成了:维护一个数据结构,支持区间加一个数,询问区间历史最大值的最大值。

线段树维护当前最大值,历史最大值。标记当前需要加上的 x ,历史最大的 x 。注意标记有时间顺序,所以需要pushdown

Code

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int MAXSIZE=30000020;
  4. int bufpos;
  5. char buf[MAXSIZE];
  6. void init(){
  7. buf[fread(buf,1,MAXSIZE,stdin)]='\0';
  8. bufpos=0;
  9. }
  10. int readint(){
  11. bool isneg;
  12. int val=0;
  13. for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++);
  14. bufpos+=(isneg=(buf[bufpos]=='-'))?1:0;
  15. for(;isdigit(buf[bufpos]);bufpos++)
  16. val=val*10+buf[bufpos]-'0';
  17. return isneg?-val:val;
  18. }
  19. char readchar(){
  20. for(;isspace(buf[bufpos]);bufpos++);
  21. return buf[bufpos++];
  22. }
  23. int readstr(char* s){
  24. int cur=0;
  25. for(;isspace(buf[bufpos]);bufpos++);
  26. for(;!isspace(buf[bufpos]);bufpos++)
  27. s[cur++]=buf[bufpos];
  28. s[cur]='\0';
  29. return cur;
  30. }
  31. typedef long long ll;
  32. const ll INF=0x3f3f3f3f3f3f3f3fLL;
  33. struct tag{
  34. ll add,curadd;
  35. tag(ll x=0){
  36. add=x;
  37. curadd=max(x,0LL);
  38. }
  39. tag& operator +=(const tag& rhs){
  40. curadd=max(curadd,add+rhs.curadd);
  41. add+=rhs.add;
  42. return *this;
  43. }
  44. };
  45. struct atom{
  46. ll mmax,curmax;
  47. atom(){
  48. mmax=curmax=0;
  49. }
  50. atom(ll mmax,ll curmax){
  51. this->mmax=mmax,this->curmax=curmax;
  52. }
  53. atom operator +(const atom& rhs)const{
  54. return atom(max(mmax,rhs.mmax),max(curmax,rhs.curmax));
  55. }
  56. atom& operator +=(const atom& rhs){
  57. return *this=*this+rhs;
  58. }
  59. atom operator +(const tag& x)const{
  60. return atom(mmax+x.add,max(curmax,mmax+x.curadd));
  61. }
  62. atom& operator +=(const tag& x){
  63. return *this=*this+x;
  64. }
  65. };
  66. const int maxn=100001;
  67. struct segtree{
  68. static const int maxt=maxn*4;
  69. atom t[maxt];
  70. tag v[maxt];
  71. int n;
  72. void init(int n){
  73. this->n=n;
  74. }
  75. void pushdown(int o){
  76. v[o*2]+=v[o];
  77. t[o*2]+=v[o];
  78. v[o*2+1]+=v[o];
  79. t[o*2+1]+=v[o];
  80. v[o]=tag();
  81. }
  82. int ul,ur,uv;
  83. void update(int o,int l,int r){
  84. if (ul<=l && ur>=r){
  85. t[o]+=uv;
  86. v[o]+=uv;
  87. return;
  88. }
  89. pushdown(o);
  90. int mid=(l+r)/2;
  91. if (ul<=mid)
  92. update(o*2,l,mid);
  93. if (ur>mid)
  94. update(o*2+1,mid+1,r);
  95. t[o]=t[o*2]+t[o*2+1];
  96. }
  97. int ql,qr;
  98. atom query(int o,int l,int r){
  99. if (ql<=l && qr>=r)
  100. return t[o];
  101. int mid=(l+r)/2;
  102. atom res;
  103. res.mmax=-INF;
  104. if (ql<=mid)
  105. res+=query(o*2,l,mid);
  106. if (qr>mid)
  107. res+=query(o*2+1,mid+1,r);
  108. return res+v[o];
  109. }
  110. }t;
  111. struct query{
  112. int p,l,r;
  113. bool operator <(const query& rhs)const{
  114. return r<rhs.r;
  115. }
  116. }q[maxn];
  117. const int delta=100000;
  118. int now[200003];
  119. int a[maxn];
  120. bool vis[200003];
  121. int lst[maxn];
  122. ll ans[maxn];
  123. int main(){
  124. init();
  125. int n=readint();
  126. t.init(n);
  127. for(int i=1;i<=n;i++){
  128. a[i]=readint();
  129. lst[i]=now[a[i]+delta];
  130. now[a[i]+delta]=i;
  131. }
  132. int m=readint();
  133. for(int i=1;i<=m;i++)
  134. q[i].p=i,q[i].l=readint(),q[i].r=readint();
  135. sort(q+1,q+m+1);
  136. int now=1;
  137. for(int i=1;i<=m;i++){
  138. while(now<=q[i].r){
  139. t.ul=lst[now]+1;
  140. t.ur=now;
  141. t.uv=a[now];
  142. t.update(1,1,n);
  143. now++;
  144. }
  145. t.ql=q[i].l,t.qr=q[i].r;
  146. ans[q[i].p]=t.query(1,1,n).curmax;
  147. }
  148. for(int i=1;i<=m;i++)
  149. printf("%lld\n",ans[i]);
  150. }

知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。

本文链接:https://www.q234rty.top/2017/04/29/bzoj2482/

隐藏