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

数据范围: n<=10^9,Q<=10^5
大力写个splay,每个节点表示一个被使用的插座或一段连续的未使用的插座形成的区间,对区间进行分裂合并.
vijos上T了...明明本机的随机极限数据在0.2s以内...
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=;
struct node{
node* ch[],*prt;
int typ,l,r;
int sz;//number of black nodes
int Maxlen,Maxpos;
node(){}
node(int _l,int _r){//white interval (include l==r)
l=_l;r=_r;ch[]=ch[]=prt=;
typ=;sz=;Maxlen=r-l+;Maxpos=l;
}
node(int x){//black
l=r=x;sz=;typ=;Maxlen=Maxpos=;ch[]=ch[]=prt=;
}
void update(){
sz=typ;
if(ch[])sz+=ch[]->sz;
if(ch[])sz+=ch[]->sz;
if(typ==){
Maxlen=r-l+;Maxpos=l;
}else{
Maxlen=Maxpos=;
}
if(ch[]){
if(ch[]->Maxlen>Maxlen){
Maxlen=ch[]->Maxlen;Maxpos=ch[]->Maxpos;
}
}
if(ch[]){
if(ch[]->Maxlen>=Maxlen){
Maxlen=ch[]->Maxlen;Maxpos=ch[]->Maxpos;
}
}
}
}t[maxn*];int tot=;
node* newnode(int l,int r){
t[++tot]=node(l,r);return t+tot;
}
node* newnode(int x){
t[++tot]=node(x);return t+tot;
}
node *root,*c0,*c1;
node* findpos(node* rt,int pos){//ordinate assert:pos exist
if(rt->l<=pos&&pos<=rt->r)return rt;
if(pos>rt->r)return findpos(rt->ch[],pos);
if(pos<rt->l)return findpos(rt->ch[],pos);
}
inline int isch1(node* rt){return rt==rt->prt->ch[];}
void rot(node* rt,int t,node* &root){
node* p=rt->prt,*c=rt->ch[t];
if(!p)root=c;
else p->ch[isch1(rt)]=c;
c->prt=p;
rt->ch[t]=c->ch[t^];
if(c->ch[t^])c->ch[t^]->prt=rt;
c->ch[t^]=rt;rt->prt=c;
rt->update();c->update();
}
void splay(node* rt,node* &root){
node *p,*g;
while((p=rt->prt)&&(g=p->prt)){
int t1=isch1(rt),t2=isch1(p);
if(t1==t2){rot(g,t2,root);rot(p,t1,root);}
else {rot(p,t1,root);rot(g,t2,root);}
}
if(p!=){
rot(p,isch1(rt),root);
}
}
void split(int l,int r){//l,r:ordinate
splay(findpos(root,l),root);
c0=root->ch[];
if(c0){
root->ch[]=;c0->prt=;root->update();
}
splay(findpos(root,r),root);
c1=root->ch[];
if(c1){
root->ch[]=;c1->prt=;root->update();
}
}
node* leftmost(node* rt){
if(rt->ch[])return leftmost(rt->ch[]);
else return rt;
}
node* rightmost(node* rt){
if(rt->ch[])return rightmost(rt->ch[]);
else return rt;
}
void merge(){
if(c0){
splay(leftmost(root),root);
root->ch[]=c0;c0->prt=root;root->update();
}
if(c1){
splay(rightmost(root),root);
root->ch[]=c1;c1->prt=root;root->update();
}
}
void query(int l,int r){
split(l,r);
printf("%d\n",root->sz);
merge();
}
void Remove(int pos){ split(pos,pos);root=newnode(pos,pos);
if(c0){
splay(rightmost(c0),c0);
if(c0->typ==){
root->ch[]=c0;c0->prt=root;root->update();c0=;
}else{
c0->r=root->r;c0->prt=;root=c0;root->update();c0=;
}
}
if(c1){
splay(leftmost(c1),c1);
if(c1->typ==){
root->ch[]=c1;c1->prt=root;root->update();c1=;
}else{//printf("!");printf("%d\n",leftmost(root)->l);
c1->l=root->l;c1->ch[]=root->ch[];
if(root->ch[])root->ch[]->prt=c1;
c1->prt=;
root=c1;root->update();c1=;
}
}
}
int Add(){
int pos=root->Maxpos+root->Maxlen/;
split(pos,pos);
if(pos>root->l){
root->ch[]=newnode(root->l,pos-);root->ch[]->prt=root; }
if(pos<root->r){
root->ch[]=newnode(pos+,root->r);root->ch[]->prt=root;
}
root->typ=;root->sz=;root->l=root->r=pos;root->Maxlen=root->Maxpos=;
root->update();
merge();
return pos;
}
int n,q;
int pos[maxn];
int L[maxn],R[maxn],K[maxn],seq[maxn],cnt;
bool cmp(const int &a,const int &b){
return K[a]<K[b];
}
int main(){
scanf("%d%d",&n,&q);
root=newnode(,n);
for(int i=;i<=q;++i){
scanf("%d",&K[i]);
if(K[i]==)scanf("%d%d",&L[i],&R[i]);
else seq[++cnt]=i;
}
sort(seq+,seq+cnt+,cmp);
int old=-,tot=;//discrete to [0,...
for(int i=;i<=cnt;++i){
if(old!=K[seq[i]]){
old=K[seq[i]];++tot;
}
K[seq[i]]=tot;
}
for(int i=;i<=q;++i){
if(K[i]==){
query(L[i],R[i]);
}else{
if(pos[K[i]]==){
pos[K[i]]=Add();
}else{
Remove(pos[K[i]]);pos[K[i]]=;
}
}
}
return ;
}

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. [原创]记一次java执行段错误及解决过程

    最近一周左右,网管监控系统经常监控到tomcat异常退出,由于有检测tomcat pid的脚本,所以会自动重启服务器,查询tomcat日志没有报错信息,查询系统message日志,可以看到如下信息. ...

  2. OracleLinux上安装数据库(DBCA)

    磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面: PostgreSQL杂记页     回到顶级页面:PostgreSQL索引页 [作者 高健@博客园  luckyjackgao@gmail. ...

  3. DSP5509之采样定理

    1. 在实际种信号是模拟连续的,但是AD采样确实离散的数字的,根据采样定理,采样频率要是模拟信号的频率2倍以上采样到的值才没问题. 2. 打开工程 unsigned ]; main() { int i ...

  4. Filter配置多个url-pattern

    java开发中会用的Filter过滤器,有时候开发需要,在一个Filter中需要配置多个过滤地址,即<url-pattern>,下面就说一下一个Filter过滤器中多个<url-pa ...

  5. 「日常训练」 Longest Run on a Snowboard (UVA-10285)

    题意 其实就是一条二维的LIS,但是还是做的一愣一愣的,多努力. 考虑$dp[i][j]$为从(i,j)出发的二维LIS的最大值,那么$dp[i][j]=max\{dp[i−di[k]][j−dj[k ...

  6. Jquery获取DOM绑定事件

    获取到当前正在执行的事件: $('#testDive').bind('click', function(event){alert('event: ' + event.type)}); 获取所有绑定事件 ...

  7. Linux命令应用大词典-第28章 硬件管理

    28.1 lscpu:显示有关CPU架构的信息 28.2 nproc:显示当前进程可用的CPU数目 28.3 chcpu:配置CPU

  8. CTC (Connectionist Temporal Classification) 算法原理

    (原创文章,转载请注明出处哦~) 简单介绍CTC算法 CTC是序列标注问题中的一种损失函数. 传统序列标注算法需要每一时刻输入与输出符号完全对齐.而CTC扩展了标签集合,添加空元素. 在使用扩展标签集 ...

  9. 3D动态人脸识别技术分析——世纪晟人脸识别实现三维人脸建模

    - 目录 - 国内3D动态人脸识别现状概况 - 新形势下人脸识别技术发展潜力 - 基于深度学习的3D动态人脸识别技术分析 1. 非线性数据建模方法 2. 基于3D变形模型的人脸建模 - 案例结合——世 ...

  10. Ubuntu16.04安装truffle时的一些错误

    1.使用truffle时出现 Error: /usr/bin/env: node: 没有那个文件或目录 1.如果是用sudo apt-get install nodejs命令安装的nodejs, ub ...