题意:小 M 的实验室有很多电源插排。这些插排的编号从 1 到 N,由左向右排成一排。
每天早晨,这些插排都是没有被使用的。每当一个学生来到实验室,他就将自己的笔记本电源插到某一个未被使用的插排上。实验室的同学们都很奇怪,他们完成这个过程是这样的:首先,他们找到还没有被使用的插排的最长区间。如果有多个区间长度相同,他们就选择最靠右的那个。然后将自己的电源插到该区间的中间。如果区间长度是偶数,他们同样选择靠右的那个。当一个同学离开实验室时,他会将自己的电源拔出来。数据保证每一个同学来到实验室时,至少有一个空的插排。
现在给你实验室同学的来到和离开事件,和一些询问。对于每一个询问,你需要计算在区间 [L,R] 已经有多少个插排被使用了。

数据范围: n<=10^9,Q<=10^5
大力写个splay,每个节点表示一个被使用的插座或一段连续的未使用的插座形成的区间,对区间进行分裂合并.
vijos上T了...明明本机的随机极限数据在0.2s以内...
  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. const int maxn=;
  5. struct node{
  6. node* ch[],*prt;
  7. int typ,l,r;
  8. int sz;//number of black nodes
  9. int Maxlen,Maxpos;
  10. node(){}
  11. node(int _l,int _r){//white interval (include l==r)
  12. l=_l;r=_r;ch[]=ch[]=prt=;
  13. typ=;sz=;Maxlen=r-l+;Maxpos=l;
  14. }
  15. node(int x){//black
  16. l=r=x;sz=;typ=;Maxlen=Maxpos=;ch[]=ch[]=prt=;
  17. }
  18. void update(){
  19. sz=typ;
  20. if(ch[])sz+=ch[]->sz;
  21. if(ch[])sz+=ch[]->sz;
  22. if(typ==){
  23. Maxlen=r-l+;Maxpos=l;
  24. }else{
  25. Maxlen=Maxpos=;
  26. }
  27. if(ch[]){
  28. if(ch[]->Maxlen>Maxlen){
  29. Maxlen=ch[]->Maxlen;Maxpos=ch[]->Maxpos;
  30. }
  31. }
  32. if(ch[]){
  33. if(ch[]->Maxlen>=Maxlen){
  34. Maxlen=ch[]->Maxlen;Maxpos=ch[]->Maxpos;
  35. }
  36. }
  37. }
  38. }t[maxn*];int tot=;
  39. node* newnode(int l,int r){
  40. t[++tot]=node(l,r);return t+tot;
  41. }
  42. node* newnode(int x){
  43. t[++tot]=node(x);return t+tot;
  44. }
  45. node *root,*c0,*c1;
  46. node* findpos(node* rt,int pos){//ordinate assert:pos exist
  47. if(rt->l<=pos&&pos<=rt->r)return rt;
  48. if(pos>rt->r)return findpos(rt->ch[],pos);
  49. if(pos<rt->l)return findpos(rt->ch[],pos);
  50. }
  51. inline int isch1(node* rt){return rt==rt->prt->ch[];}
  52. void rot(node* rt,int t,node* &root){
  53. node* p=rt->prt,*c=rt->ch[t];
  54. if(!p)root=c;
  55. else p->ch[isch1(rt)]=c;
  56. c->prt=p;
  57. rt->ch[t]=c->ch[t^];
  58. if(c->ch[t^])c->ch[t^]->prt=rt;
  59. c->ch[t^]=rt;rt->prt=c;
  60. rt->update();c->update();
  61. }
  62. void splay(node* rt,node* &root){
  63. node *p,*g;
  64. while((p=rt->prt)&&(g=p->prt)){
  65. int t1=isch1(rt),t2=isch1(p);
  66. if(t1==t2){rot(g,t2,root);rot(p,t1,root);}
  67. else {rot(p,t1,root);rot(g,t2,root);}
  68. }
  69. if(p!=){
  70. rot(p,isch1(rt),root);
  71. }
  72. }
  73. void split(int l,int r){//l,r:ordinate
  74. splay(findpos(root,l),root);
  75. c0=root->ch[];
  76. if(c0){
  77. root->ch[]=;c0->prt=;root->update();
  78. }
  79. splay(findpos(root,r),root);
  80. c1=root->ch[];
  81. if(c1){
  82. root->ch[]=;c1->prt=;root->update();
  83. }
  84. }
  85. node* leftmost(node* rt){
  86. if(rt->ch[])return leftmost(rt->ch[]);
  87. else return rt;
  88. }
  89. node* rightmost(node* rt){
  90. if(rt->ch[])return rightmost(rt->ch[]);
  91. else return rt;
  92. }
  93. void merge(){
  94. if(c0){
  95. splay(leftmost(root),root);
  96. root->ch[]=c0;c0->prt=root;root->update();
  97. }
  98. if(c1){
  99. splay(rightmost(root),root);
  100. root->ch[]=c1;c1->prt=root;root->update();
  101. }
  102. }
  103. void query(int l,int r){
  104. split(l,r);
  105. printf("%d\n",root->sz);
  106. merge();
  107. }
  108. void Remove(int pos){
  109.  
  110. split(pos,pos);root=newnode(pos,pos);
  111. if(c0){
  112. splay(rightmost(c0),c0);
  113. if(c0->typ==){
  114. root->ch[]=c0;c0->prt=root;root->update();c0=;
  115. }else{
  116. c0->r=root->r;c0->prt=;root=c0;root->update();c0=;
  117. }
  118. }
  119. if(c1){
  120. splay(leftmost(c1),c1);
  121. if(c1->typ==){
  122. root->ch[]=c1;c1->prt=root;root->update();c1=;
  123. }else{//printf("!");printf("%d\n",leftmost(root)->l);
  124. c1->l=root->l;c1->ch[]=root->ch[];
  125. if(root->ch[])root->ch[]->prt=c1;
  126. c1->prt=;
  127. root=c1;root->update();c1=;
  128. }
  129. }
  130. }
  131. int Add(){
  132. int pos=root->Maxpos+root->Maxlen/;
  133. split(pos,pos);
  134. if(pos>root->l){
  135. root->ch[]=newnode(root->l,pos-);root->ch[]->prt=root;
  136.  
  137. }
  138. if(pos<root->r){
  139. root->ch[]=newnode(pos+,root->r);root->ch[]->prt=root;
  140. }
  141. root->typ=;root->sz=;root->l=root->r=pos;root->Maxlen=root->Maxpos=;
  142. root->update();
  143. merge();
  144. return pos;
  145. }
  146. int n,q;
  147. int pos[maxn];
  148. int L[maxn],R[maxn],K[maxn],seq[maxn],cnt;
  149. bool cmp(const int &a,const int &b){
  150. return K[a]<K[b];
  151. }
  152. int main(){
  153. scanf("%d%d",&n,&q);
  154. root=newnode(,n);
  155. for(int i=;i<=q;++i){
  156. scanf("%d",&K[i]);
  157. if(K[i]==)scanf("%d%d",&L[i],&R[i]);
  158. else seq[++cnt]=i;
  159. }
  160. sort(seq+,seq+cnt+,cmp);
  161. int old=-,tot=;//discrete to [0,...
  162. for(int i=;i<=cnt;++i){
  163. if(old!=K[seq[i]]){
  164. old=K[seq[i]];++tot;
  165. }
  166. K[seq[i]]=tot;
  167. }
  168. for(int i=;i<=q;++i){
  169. if(K[i]==){
  170. query(L[i],R[i]);
  171. }else{
  172. if(pos[K[i]]==){
  173. pos[K[i]]=Add();
  174. }else{
  175. Remove(pos[K[i]]);pos[K[i]]=;
  176. }
  177. }
  178. }
  179. return ;
  180. }

vijos1859[TJOI2014]电源插排的更多相关文章

  1. P3968 [TJOI2014]电源插排

    P3968 [TJOI2014]电源插排 线段树维护最长空区间及左端点位置,这个和$nlongn$的动态最大子序和差不多,就不多解释了 $n$较大哈希优化空间 My complete code: #i ...

  2. [BZOJ 5155][Tjoi2014]电源插排

    传送门 网上大部分题解都写得是动态开点线段树,然而像\(MiEcoku\)这么懒惰的显然不会去写线段树... \(\color{green}{solution}\) 我们考虑来点骚操作. 线段树维护的 ...

  3. TJOI2014

    匹配 给出一个\(n(n\leq80)\)个点对\(n\)个点的带权二分图,求所有最大权匹配的交集. 先求出一个最大权匹配,然后枚举每一条匹配中的边,检验删除该边后是否还能形成最大权匹配.如果能则说明 ...

  4. bzoj5157: [Tjoi2014]上升子序列(树状数组LIS)

    5157: [Tjoi2014]上升子序列 题目:传送门 题解: 学一下nlogn的树状数组求最长上生子序列就ok(%爆大佬) 离散化之后,用一个数组记录一下,直接树状数组做 吐槽:妈耶...一开始不 ...

  5. [TJOI2014]拼图

    嘟嘟嘟 一眼看上去像状压dp,然后越想复杂度越不对劲,最后发现和爆搜差不多,索性就写爆搜了,复杂度\(O(\)能过\()\). 别忘了填拼图和回溯的时候只动拼图中是1的部分,不要把\(n * m\)的 ...

  6. [TJOI2014]Alice and Bob[拓扑排序+贪心]

    题意 给出一个序列的以每一项结尾的 \(LIS\) 的长度a[],求一个序列,使得以每一项为开头的最长下降子序列的长度之和最大. \(n\leq 10^5\) . 分析 最优解一定是一个排列,因为如果 ...

  7. 【bzoj5157】[Tjoi2014]上升子序列 树状数组

    题目描述 求一个数列本质不同的至少含有两个元素的上升子序列数目模10^9+7的结果. 题解 树状数组 傻逼题,离散化后直接使用树状数组统计即可.由于要求本质不同,因此一个数要减去它前一次出现时的贡献( ...

  8. [BZOJ 5158][Tjoi2014]Alice and Bob

    传送门 \(\color{green}{solution}\) 贪心 /************************************************************** P ...

  9. 【[TJOI2014]上升子序列】

    这本质上是一个\(dp\) 如果没有"两个上升子序列相同,那么只需要计算一次"这一个性质,那么就很好做了,我们用\(dp[i]\)表示以\(i\)结尾的上升子序列个数,那么就有\( ...

随机推荐

  1. POJ2431_Expedition_KEY

    题目传送门 由题目可得,在一条路上有N个加油站,在距离终点a[i](细节)的位置上,你需要通过长度为L的路,油箱的容量是无限的,但是初始只有P点油,经过每个加油站时可以选择加b[i]的油,问最少加油几 ...

  2. Mybatis简单入门

    前言 之前一直有直接使用Mybatis,但是没有细致的整理出来.长时间没有使用,细致的内容都忘记了.因此借此机会,从头开始整理,以后可以直接查看此次记录的内容. Mybatis的介绍 MyBatis是 ...

  3. Python:pickle模块学习

    1. pickle模块的作用 将字典.列表.字符串等对象进行持久化,存储到磁盘上,方便以后使用 2. pickle对象串行化 pickle模块将任意一个python对象转换成一系统字节的这个操作过程叫 ...

  4. js实现无限级分类

    let arr = [ {id:1,name:"php",pid:0}, {id:2,name:"php基础",pid:1}, {id:3,name:" ...

  5. 「日常训练」Queue(Codeforces Round 303 Div.2 D)

    简单到让人不敢相信是D题,但是还是疏忽了一点. 题意与分析 (Codeforces 545D) 题意:n人排队,当一个人排队的时间超过他需要服务的时间就会厌烦,现在要求一个最优排列使得厌烦的人最少. ...

  6. uvaoj 1081510815 - Andy's First Dictionary(set应用)

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=835&page= ...

  7. 韦大仙--简单的monkey测试命令行操作及生成log日志保存

    作中,在将apk交给软件测试人员去测试之前,不免要自己先自测,monkey自测是一个不错的选择! 步骤很简单: 1.测试用的手机与电脑连接好USB ,并且安装好驱动(我一般都是通过豌豆荚自动安装的)! ...

  8. C do whlie 数数位

    #include <stdio.h> int main(int argc, char **argv) {    //定义两个变量 x 跟 n,n的初始化为0:  int x;  int n ...

  9. visionpro9.0破解

    visionpro9.0软件下载 提供一个visionpro9.0视频教程学习网站:点击下面链接进入. ------------------------Halcon,Visionpro高清视频教程,点 ...

  10. NMAP-主机扫描

    1.全面扫描 2.扫描指定段 3.ping扫描 只进行ping操作,十分隐蔽 4.无ping扫描 适用于防火墙禁止ping 5.TCP SYN扫描 6.TCP ACK扫描 7.UDP扫描 8.ICMP ...