题目大意

  有一个双端队列,每个元素是一个物品,每个物品有体积和价值两个属性。

  有 \(n\) 个操作,分为 \(5\) 种:前后端插入删除,还有询问:选出一些物品,满足这些物品的体积之和模 \(p\) 在 \([l,r]\) 之间,问你价值和最大是多少。

  \(n\leq 50000,p\leq 500\)

题解

离线做法

  处理出每个物品加入队列的时间和删除的时间,插入到线段树里面分治就好了。

  时间复杂度:\(O(np\log n)\)

在线做法

  考虑对于一个队列,从中间向两边各建一个可持久化栈维护两边中间到两边的物品加在一起的信息。

  如果删除后把某一个栈的栈底删掉了,就从中间开始重构这两个栈。

  对于一个询问,枚举左边的物品体积是多少,然后右边的物品体积就是一个区间。

  可以按照 \(r-l+1\) 分块,这样每次询问就是块内的一个前缀和一个后缀。

  时间复杂度:\(O(np)\)

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cstdlib>
  5. #include<ctime>
  6. #include<utility>
  7. #include<functional>
  8. #include<cmath>
  9. #include<vector>
  10. //using namespace std;
  11. using std::min;
  12. using std::max;
  13. using std::swap;
  14. using std::sort;
  15. using std::reverse;
  16. using std::random_shuffle;
  17. using std::lower_bound;
  18. using std::upper_bound;
  19. using std::unique;
  20. using std::vector;
  21. typedef long long ll;
  22. typedef unsigned long long ull;
  23. typedef double db;
  24. typedef std::pair<int,int> pii;
  25. typedef std::pair<ll,ll> pll;
  26. void open(const char *s){
  27. #ifndef ONLINE_JUDGE
  28. char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
  29. #endif
  30. }
  31. void open2(const char *s){
  32. #ifdef DEBUG
  33. char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
  34. #endif
  35. }
  36. int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
  37. void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
  38. int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
  39. int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
  40. const int N=50010;
  41. const int P=510;
  42. const ll inf=0x3fffffffffffffffll;
  43. struct info
  44. {
  45. ll a[P];
  46. ll &operator [](int x)
  47. {
  48. return a[x];
  49. }
  50. void clear()
  51. {
  52. memset(a,0xc0,sizeof a);
  53. a[0]=0;
  54. }
  55. };
  56. int n,p;
  57. info a1[N],a2[N];
  58. int l,r,mid;
  59. int t1,t2;
  60. int w[2*N],v[2*N];
  61. void init()
  62. {
  63. l=50001;
  64. r=50000;
  65. mid=50000;
  66. a1[0].clear();
  67. a2[0].clear();
  68. }
  69. void addl(int x)
  70. {
  71. t1++;
  72. a1[t1]=a1[t1-1];
  73. for(int i=0;i<p;i++)
  74. a1[t1][(i+w[x])%p]=max(a1[t1][(i+w[x])%p],a1[t1-1][i]+v[x]);
  75. }
  76. void addr(int x)
  77. {
  78. t2++;
  79. a2[t2]=a2[t2-1];
  80. for(int i=0;i<p;i++)
  81. a2[t2][(i+w[x])%p]=max(a2[t2][(i+w[x])%p],a2[t2-1][i]+v[x]);
  82. }
  83. void rebuild()
  84. {
  85. mid=(l+r)>>1;
  86. t1=0;
  87. t2=0;
  88. for(int i=mid;i>=l;i--)
  89. addl(i);
  90. for(int i=mid+1;i<=r;i++)
  91. addr(i);
  92. }
  93. int pre[P],suf[P];
  94. void query()
  95. {
  96. int ql,qr;
  97. scanf("%d%d",&ql,&qr);
  98. int len=qr-ql+1;
  99. ll s=-inf;
  100. for(int i=0;i<p;i++)
  101. {
  102. if(i%len==0)
  103. s=-inf;
  104. s=max(s,a1[t1][i]);
  105. pre[i]=s;
  106. }
  107. s=-inf;
  108. for(int i=p-1;i>=0;i--)
  109. {
  110. if(i%len==len-1)
  111. s=-inf;
  112. s=max(s,a1[t1][i]);
  113. suf[i]=s;
  114. }
  115. ll ans=-1;
  116. // for(int i=0;i<p;i++)
  117. // for(int j=0;j<p;j++)
  118. // if((i+j)%p>=ql&&(i+j)%p<=qr)
  119. // {
  120. // ans=max(ans,a1[t1][i]+a2[t2][j]);
  121. // if(ans==481594)
  122. // int xxx=1;
  123. // }
  124. for(int i=0;i<p;i++)
  125. {
  126. int _l=ql-i;
  127. int _r=qr-i;
  128. if(_l<0)
  129. _l+=p;
  130. if(_r<0)
  131. _r+=p;
  132. ans=max(ans,a2[t2][i]+max(pre[_r],suf[_l]));
  133. int z=p/len*len;
  134. if(_l>_r&&_l<z)
  135. ans=max(ans,a2[t2][i]+suf[z]);
  136. }
  137. printf("%lld\n",ans);
  138. }
  139. char op[10];
  140. void gao()
  141. {
  142. scanf("%s",op);
  143. if(op[0]=='I')
  144. {
  145. if(op[1]=='F')
  146. {
  147. l--;
  148. scanf("%d%d",&w[l],&v[l]);
  149. w[l]%=p;
  150. addl(l);
  151. }
  152. else
  153. {
  154. r++;
  155. scanf("%d%d",&w[r],&v[r]);
  156. w[r]%=p;
  157. addr(r);
  158. }
  159. }
  160. else if(op[0]=='D')
  161. {
  162. if(op[1]=='F')
  163. {
  164. l++;
  165. t1--;
  166. if(l>mid+1)
  167. rebuild();
  168. }
  169. else
  170. {
  171. r--;
  172. t2--;
  173. if(r<=mid+1)
  174. rebuild();
  175. }
  176. }
  177. else
  178. {
  179. query();
  180. }
  181. }
  182. int main()
  183. {
  184. open("loj6515");
  185. rd();
  186. scanf("%d%d",&n,&p);
  187. init();
  188. for(int i=1;i<=n;i++)
  189. {
  190. if(i==75)
  191. int xxx=1;
  192. gao();
  193. // if(op[0]=='Q')
  194. // printf("%d\n",i);
  195. }
  196. return 0;
  197. }

【LOJ6515】贪玩蓝月的更多相关文章

  1. 【线段树分治 01背包】loj#6515. 「雅礼集训 2018 Day10」贪玩蓝月

    考试时候怎么就是没想到线段树分治呢? 题目描述 <贪玩蓝月>是目前最火爆的网页游戏.在游戏中每个角色都有若干装备,每件装备有一个特征值 $w$ 和一个战斗力 $v$ .在每种特定的情况下, ...

  2. 2019.01.13 loj#6515. 贪玩蓝月(线段树分治+01背包)

    传送门 题意简述:有一个初始为空的双端队列,每次可以在队首和队尾插入或弹出一个二元组(wi,vi)(w_i,v_i)(wi​,vi​),支持询问从当前队列中选取若干个元素是的他们的和对 MODMODM ...

  3. 「雅礼集训 2018 Day10」贪玩蓝月

    题目链接 题意分析 我们考虑维护两个栈 分别支持左边的插入删除以及右边的插入删除 然后对于两两个栈的我们需要用背包求出最优答案 注意 删除时如果不够的话 我们需要从另一个栈中取出一半加入另一个栈中 注 ...

  4. loj #6515. 「雅礼集训 2018 Day10」贪玩蓝月

    \(\color{#0066ff}{输入样例}\) 0 11 10 QU 0 0 QU 1 9 IG 14 7 IF 3 5 QU 0 9 IG 1 8 DF QU 0 4 IF 1 2 DG QU ...

  5. Python 正则表达式 (python网络爬虫)

    昨天 2018 年 01 月 31 日,农历腊月十五日.20:00 左右,152 年一遇的月全食.血月.蓝月将今晚呈现空中,虽然没有看到蓝月亮,血月.月全食也是勉强可以了,还是可以想像一下一瓶蓝月亮洗 ...

  6. 基于H5的混合开发介绍(一)WebView

    转自: https://www.cnblogs.com/sanchang/p/9261461.html 一 WebView到底是什么    1 WebView是一种控件,它基于webkit引擎,因此具 ...

  7. python语言学习--2

    第三天1. python代码缩进规则:具有相同缩进的代码被视为代码块,4个空格, 不要使用Tab,更不要混合Tab和空格,否则很容易造成因为缩进引起的语法错误. 2.list:[...] 用(名称任意 ...

  8. html5常见新增标签

    本文内容: header nav article footer section aside datalist 音频标签: audio 视频标签: video 插入媒体标签: embed 新增input ...

  9. Python爬取电影天堂指定电视剧或者电影

    1.分析搜索请求 一位高人曾经说过,想爬取数据,要先分析网站 今天我们爬取电影天堂,有好看的美剧我在上面都能找到,算是很全了. 这个网站的广告出奇的多,用过都知道,点一下搜索就会弹出个窗口,伴随着滑稽 ...

随机推荐

  1. DSAPI+DS控件库 Windows7风格控件演示

    效果图 部分代码 DSAPI.Win7特性.任务栏特效.初始化() '这句非常重要,很多对任务栏特性的操作都需要先初始化 DSAPI.Win7特性.设置任务栏窗口缩略图(Me, My.Resource ...

  2. Java虚拟机判定对象存活算法

    1.引用计数算法 描述:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器值为0的对象就是不可能再被使用的. 特点:实现简单,判定效率高. ...

  3. Django学习之八:forms组件【对form舒心了】

    目录 Django forms组件 bound and unbound form instance forms渲染有关 隐藏一个字段,不渲染它 form 校验 form类 ModelForm 利用Mo ...

  4. Ext JS中的typeOf

    Ext JS中的typeOf:以字符串格式,返回给定变量的类型 其中对字符串对象.元素节点.文本节点.空白文本节点判断并不准确 测试代码如下: <!DOCTYPE HTML PUBLIC &qu ...

  5. Swiper4.x使用方法

    1.首先加载插件,需要用到的文件有swiper.min.js和swiper.min.css文件.可下载Swiper文件或使用CDN. <!DOCTYPE html> <html> ...

  6. 自动化测试 Appium之Python运行环境搭建 Part1

    Appium之Python运行环境搭建 Part1 by:授客 QQ:1033553122 实践环境 Win7 Python 3.4.0 JAVA JDK 1.8.0_121 node.js8.11. ...

  7. Android项目实战(四十五):Zxing二维码切换横屏扫描

    Demo链接 默认是竖屏扫描,但是当我们在清单文件中配置横屏显示的时候: <activity android:name=".CaptureActivity" android: ...

  8. 自己动手写事件总线(EventBus)

    本文由云+社区发表 事件总线核心逻辑的实现. EventBus的作用 Android中存在各种通信场景,如Activity之间的跳转,Activity与Fragment以及其他组件之间的交互,以及在某 ...

  9. 路由刷rom手册

    最近对家里面那5,6个路由器下手了. 路由列表:小米mini 2台. 优酷路由宝l1,tp wdr3320,tp wr840n,  友华wr1200js,小米路由r1n 步骤: 1. 想办法开启ssh ...

  10. selenium-测试框架搭建(十三)

    思路 分离业务代码和测试数据,提高代码可维护性,实现自动化,减少重复劳动. 一个测试框架大概由配置文件,测试数据,测试用例,相关文件(发送邮件等),测试日志,断言和测试报告等模块组成. 结构 以页面为 ...