传送门

网上大部分题解都写得是动态开点线段树,然而像\(MiEcoku\)这么懒惰的显然不会去写线段树...

\(\color{green}{solution}\)

我们考虑来点骚操作. 线段树维护的是区间最长连续空段,那么我们能不能单独把空的区间提出来呢?这样就可以
不用线段树了.

对于连续的一段空区间,我们可以用一个\(set\)去维护. 那么空区间的问题解决了,现在怎么求区间内有多少个插排被使用呢?
这...如果没有同学离开,那么随便用一个数据结构就可以维护. 但因为我 们需要支持删除操作,所以我用平衡树维护.

具体的删除操作:
在一位同学离开后,假设他的位置是\(p\), 他前面第一个被使用的位置是\(p_l\), 他后面第一个
被使用的位置是\(p_r\), 那么我们只需要再\(set\)中删除区间 \([p_l+1, p-1]\) 和区间 \([p+1, p_r-1]\)(如果区间存在)
再将区间 \([p_l+1, p_r-1]\) 加入\(set\)即可

具体实现详见代码

#include <bits/stdc++.h>
using namespace std;

const int maxn = 100010;

struct line {
    int l, r;
    bool operator < (const line &a) const {
        return r-l == a.r-a.l ? r > a.r : r-l > a.r-a.l;
    }
    line (int l, int r) : l(l), r(r) {}
    line () {}
};
set<line> tc; map<int, int> id;
struct node {int v, ky, sz; node *ls, *rs;};
node *nul, pool[maxn], *pis = pool, *rt;
inline void init() {
    nul=pis; nul->ls=nul->rs=nul; nul->sz=0; rt=nul; srand(19260817);
}
node *newnode(int val) {
    node *k = ++ pis; k->ls = k->rs = nul;
    k->v=val; k->sz = 1; k->ky = rand(); return k;
}
inline void up(node *&x) { x->sz = x->ls->sz + x->rs->sz + 1;}
inline void spl(node *c, node *&x, node *&y, int val) {
    if( c == nul) { x = y = nul; return;}
    if( c->v <= val) x = c, spl(c->rs, x->rs, y, val);
    else y = c, spl(c->ls, x, y->ls, val); up(c);
}
inline void mrg(node *&c, node *x, node *y) {
    if( x==nul || y==nul) {c = x==nul ? y : x; return;}
    if( x->ky < y->ky) c = x, mrg(c->rs, x->rs, y);
    else c = y, mrg(c->ls, x, y->ls); up(c);
}
int insert() {
    line c = *tc.begin(); tc.erase(tc.begin());
    int pos = c.r + c.l + 1 >> 1;
    tc.insert(line(c.l,pos-1)); tc.insert(line(pos+1,c.r));
//  printf("%d -\n", pos); // de bug
    node *x, *y;
    spl(rt, x, y, pos); mrg(x, x, newnode(pos)); mrg(rt, x, y);
    return pos;
}
inline void erase(int opt) {
    node *x, *y, *z, *c; spl(rt, x, y, opt); spl(x, x, z, opt-1);
    int l, r;
    c=x; while( c->rs!=nul) c = c->rs; l = c->v;
    c=y; while( c->ls!=nul) c = c->ls; r = c->v;
    mrg(rt, x, y);
    tc.erase(line(l+1, opt-1)); tc.erase(line(opt+1, r-1));
    tc.insert(line(l+1, r-1));
}
inline void modify(int opt) {
    if( id[opt]) erase(id[opt]), id[opt] = 0;
    else id[opt] = insert();
}
inline void qry(int l, int r) {
    node *x, *y, *z; spl(rt, x, y, r); spl(x, x, z, l-1);
    printf("%d\n", z->sz); mrg(x, x, z); mrg(rt, x, y);
}
int n, Q;
int main() {
#ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("b.out","w",stdout);
#endif
    init();
    scanf("%d%d", &n, &Q); tc.insert(line(1, n));
    mrg(rt, rt, newnode(0)); mrg(rt, rt, newnode(n+1));
    for ( register int i = 1, opt, l, r; i <= Q; ++ i) {
        scanf("%d", &opt);
        if( opt) modify(opt);
        else scanf("%d%d", &l, &r), qry(l, r);
    }
    return 0;
}

[BZOJ 5155][Tjoi2014]电源插排的更多相关文章

  1. P3968 [TJOI2014]电源插排

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

  2. vijos1859[TJOI2014]电源插排

    题意:小 M 的实验室有很多电源插排.这些插排的编号从 1 到 N,由左向右排成一排.每天早晨,这些插排都是没有被使用的.每当一个学生来到实验室,他就将自己的笔记本电源插到某一个未被使用的插排上.实验 ...

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

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

  4. 【刷题】BZOJ 5154 [Tjoi2014]匹配

    Description 有N个单身的男孩和N个单身女孩,男孩i和女孩j在一起得到的幸福值为Hij.一个匹配即对这N个男孩女孩的安排: 每个男孩恰好有一个女朋友,每个女孩恰好有一个男朋友.一个匹配的幸福 ...

  5. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  6. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  7. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  8. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  9. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

随机推荐

  1. GPS坐标换算为百度坐标(转)

    最近在做一个关于手机定位的小应用,需求是这样的,用户通过手机(Wp8)进行二维码扫描操作并且记录用户的当前位置,在PC上可以查看用户所在地图的位置,做法就是在用户扫描条码时,通过手机GPS获取当前在地 ...

  2. 获取iPod library中的媒体文件

    [获取iPod library中的媒体文件] The Media Player framework provides facilities for playing movie, music, audi ...

  3. 在VMware中设置CentOS7的网络

    为了能够使用XShell来管理我们安装好的CentOS7系统,所以我们要先设置CentOS7的网络使其能够联网.  1.选择vmware的编辑,然后点击虚拟网络编辑器     2.点击更改设置(需要有 ...

  4. java内存溢出异常

    名称 特征 作用 配置参数 异常 程序 计数器 占用内存小,线程私有, 生命周期与线程相同 大致为字节码行号指示器 无 无 虚拟机栈 线程私有,生命周期与线程 相同,使用连续的内存空间 Java 方法 ...

  5. Oracle EBS Patch Demo

    Oracle EBS APP & DB 打补丁过程简述l例子: 打 Patch#   11843100:R12.CAC.B 打PATCH之前先查询一下是否已经有了这个PATCH. SELECT ...

  6. 点滴笔记(一):for循环ajax请求添加数据

    项目里遇到循环添加数据,添加多条数据到主表后,还要根据每条主表数据主键ID添加到子表里,于是想到post提交 发现循环post没效果,也没async参数.. 于是用ajax里面有async设置了fal ...

  7. Android-工作总结-LX-2018-08-20-判断数据库表字段是否为空

    问题的因素: 调试了一上午,我要判断数据库表的name字段是否为空,使用了TextUtils.isEmpty(nameStr):来判断name字段是否为空,明明数据库是没有值,却一直显示有值,然后还去 ...

  8. .NET中Debug模式与Release模式差别

    Debug里的PDB是full,保存着调试和项目状态信息.有断言.堆栈检查等代码.Release 里的PDB是pdb-only,基本上:出什么错了+错误在哪行. 因为很多人把PDB理解成:调试文件.P ...

  9. SQL Server Job

    1. SQL Server Job创建:(SQL Server 代理 - 作业)鼠标右键.新建作业. 2.[常规]选项:定义作业名称.和说明信息. 3:[步骤]选项:新建步骤 4:定义步骤名称.设置对 ...

  10. Mysql修改字段类型

    mysql 修改字段长度 alter table news  modify column title varchar(130); alter table 表名 modify column 字段名 类型 ...