1 条题解
-
0
自动搬运
来自洛谷,原作者为

Froggy
最初的一步,泪水之后再一次,雕刻的风景线,消逝在黄昏中的风,直到梦的最后。—— Clannad搬运于
2025-08-24 21:55:03,当前版本为作者最后更新于2020-01-08 11:49:23,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
set,动态开点线段树¿¿¿ 为什么不挑战一下动态开点 ¿¿¿
这样写代码难度很高,但未尝不是锻炼代码能力的一种方法, [大雾]
(珂能我写复杂了,常数巨大,吸氧才过)其实这道题csp2019前一天就写了一上午,写呱了,心态炸了,期末考试完了拐回头重构代码,终于A了
由于是动态开点平衡树,所以每个节点记录一个区间
len为该节点代表的区间长度,即siz为以该节点为根的子树所构成的区间大小 (注意区分上面两个,否则写着写着就混淆了)询问操作
好办,
val记录该节点被使用的插排个数,sum以该节点为根的子树被使用的插排个数更新节点信息的时候这样就好了
t[k].siz=t[ls].siz+t[rs].siz+t[k].len; t[k].sum=t[ls].sum+t[rs].sum+t[k].val;询问的时候把区间分裂出来输出sum
重点是----
插入/删除操作
要找到长度最大的连续一段空插座
需要维护
maxlen即和要插的位置
mid即如果维护了这两个,那么就不需要维护
mxl和mxr了.lmax和rmax,即最左/右边连续空插座的个数举个例子:
比如一段插座长这样:(1表示有电源插入,0表示空)
110100001000那么lmax=0, rmax=3, maxlen=4 ,mid=(5+8+1)/2
要插入的位置就很显然了:
t[root].mid还需要开个
map::vis方便下一次删除现在考虑如何维护:
维护
lmax和rmax很套路,不说了分别取左右子树的maxlen的最大值
当
t[k].val==0的时候还要特殊讨论:跨节点k的一段空插座长度为
t[k].len+t[ls].rmax+t[rs].lmax更新一下就好了啦~
inline void update(int k){ #define ls t[k].ch[0] #define rs t[k].ch[1] t[k].siz=t[ls].siz+t[rs].siz+t[k].len; t[k].maxlen=0; t[k].sum=t[ls].sum+t[rs].sum+t[k].val; t[k].lmax=t[ls].lmax; t[k].rmax=t[rs].rmax; if(ls){//从左子树更新 t[k].maxlen=t[ls].maxlen; t[k].mid=t[ls].mid; } if(t[k].val==0){ //跨左右子树讨论 if(t[ls].sum==0){ t[k].lmax=t[ls].lmax+t[k].len+t[rs].lmax; } if(t[rs].sum==0){ t[k].rmax=t[ls].rmax+t[k].len+t[rs].rmax; } int len=t[k].len+t[ls].rmax+t[rs].lmax; if(len>=t[k].maxlen){ t[k].maxlen=len; t[k].mid=(t[k].l-t[ls].rmax+t[k].r+t[rs].lmax+1)>>1; } } if(t[rs].maxlen>=t[k].maxlen){ //从右子树更新 t[k].maxlen=t[rs].maxlen; t[k].mid=t[rs].mid; } #undef ls #undef rs }code:
#include<iostream> #include<cstdio> #include<map> #include<cstdlib> using namespace std; #define N 100010 inline int read(){ int x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } return x*f; } map<int,int> mp,vis; int n,Q,root,cnt; struct node{ int ch[2],key,l,r,val,sum,siz,len; int mid,lmax,rmax,maxlen; }t[N<<3]; inline int NewNode(int l,int r){ int k=++cnt; t[k].key=rand(); t[k].l=l,t[k].r=r; t[k].mid=(l+r+1)>>1; t[k].ch[0]=t[k].ch[1]=0; t[k].val=t[k].sum=0; t[k].maxlen=t[k].siz=t[k].len=t[k].lmax=t[k].rmax=r-l+1; mp[r]=k; return k; } inline void update(int k){ #define ls t[k].ch[0] #define rs t[k].ch[1] t[k].siz=t[ls].siz+t[rs].siz+t[k].len; t[k].maxlen=0; t[k].sum=t[ls].sum+t[rs].sum+t[k].val; t[k].lmax=t[ls].lmax; t[k].rmax=t[rs].rmax; if(ls){ t[k].maxlen=t[ls].maxlen; t[k].mid=t[ls].mid; } if(t[k].val==0){ if(t[ls].sum==0){ t[k].lmax=t[ls].lmax+t[k].len+t[rs].lmax; } if(t[rs].sum==0){ t[k].rmax=t[ls].rmax+t[k].len+t[rs].rmax; } int len=t[k].len+t[ls].rmax+t[rs].lmax; if(len>=t[k].maxlen){ t[k].maxlen=len; t[k].mid=(t[k].l-t[ls].rmax+t[k].r+t[rs].lmax+1)>>1; } } if(t[rs].maxlen>=t[k].maxlen){ t[k].maxlen=t[rs].maxlen; t[k].mid=t[rs].mid; } #undef ls #undef rs } int Merge(int l,int r){ if(!l||!r)return l+r; if(t[l].key<t[r].key){ t[l].ch[1]=Merge(t[l].ch[1],r); update(l); return l; } else{ t[r].ch[0]=Merge(l,t[r].ch[0]); update(r); return r; } } void Split(int k,int data,int &l,int &r){ if(!k){ l=r=0; return; } if(t[k].r<=data){ l=k; Split(t[k].ch[1],data,t[k].ch[1],r); } else{ r=k; Split(t[k].ch[0],data,l,t[k].ch[0]); } update(k); } inline void New(int pos){ int k=mp.lower_bound(pos)->second; int x=t[k].l,y=t[k].r; if(x==y&&x==pos)return; int l,p,r; Split(root,y,l,r); Split(l,x-1,l,p); mp.erase(t[k].r); if(pos>x){ l=Merge(l,NewNode(x,pos-1)); } if(y>pos){ r=Merge(NewNode(pos+1,y),r); } root=Merge(Merge(l,NewNode(pos,pos)),r); } inline int Query(int x,int y){ New(x),New(y); int l,p,r; Split(root,y,l,r); Split(l,x-1,l,p); int ans=t[p].sum; root=Merge(Merge(l,p),r); return ans; } inline void Delete(int pos){ int l,p,r; Split(root,pos,l,r); Split(l,pos-1,l,p); t[p].val=t[p].sum=0; t[p].mid=pos,t[p].maxlen=t[p].lmax=t[p].rmax=t[p].len; root=Merge(Merge(l,p),r); } inline void Change(int pos){ New(pos); int l,p,r; Split(root,pos,l,r); Split(l,pos-1,l,p); t[p].val=t[p].sum=1; t[p].mid=t[p].maxlen=t[p].lmax=t[p].rmax=0; root=Merge(Merge(l,p),r); } int main(){ n=read(),Q=read(); root=NewNode(1,n); while(Q--){ int x=read(); if(x==0){ int l=read(),r=read(); printf("%d\n",Query(l,r)); } else{ if(vis.count(x)){ Delete(vis[x]); vis.erase(x); } else{ vis[x]=t[root].mid; Change(t[root].mid); } } } return 0; }呱!!
- 1
信息
- ID
- 2920
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者