题解:P11488 「Cfz Round 5」Zhòng shù
我这写的也太详细了。
首先大概还是要维护一下树的结构的,不过显然不能全部维护,所以每次
更具体的,我们应当对一个节点记录
现在一个节点代表着若干条链,如果我们要对其中一个链的其中一个点做一些事情,那么这些链就并不完全一样了。我们只需要把这条将要操作的链从中 split 出来,它就只代表它自己了。
更具体的,设这个点表示了
还有一个问题是我们如何找到原树的第
那么
然后我们好像还有一个查询操作,所有修改在深度上都是区间加的形式,动态开点线段树即可。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#define ll long long
using namespace std;
typedef pair<ll,int> P;
const int MAXN=3e5+10;
const int MAXT=1.3e7;
const ll INF=1e18;
int m,tot=1,fa[MAXN];ll n=1;
struct node{ll pos,l,k,d;}t[MAXN];
set <P> s,v[MAXN];
namespace T
{
struct node{ll num,add;int ls,rs;}t[MAXT];int tot=1;
inline void upd(int p,ll z)
{t[p].num+=z,t[p].add+=z;}
inline void push_down(int p)
{
upd(t[p].ls,t[p].add),upd(t[p].rs,t[p].add);
t[p].add=0;return ;
}
inline void push_up(int p)
{t[p].num=max(t[t[p].ls].num,t[t[p].rs].num);}
void add(ll l,ll r,int p,ll x,ll y,ll z)
{
if(x<=l&&y>=r){upd(p,z);return ;}
if(!t[p].ls) t[p].ls=++tot,t[p].rs=++tot;
ll mid=(l+r)>>1;push_down(p);
if(x<=mid) add(l,mid,t[p].ls,x,y,z);
if(y>mid) add(mid+1,r,t[p].rs,x,y,z);
push_up(p);return ;
}
inline void A(ll l,ll r,ll x){add(1,INF,1,l,r,x);}
}
inline int find(ll x)//找到对应节点
{
auto it=s.lower_bound({x,MAXN});
return prev(it)->second;
}
inline void create(int p,ll pos,ll l,ll k,ll d)//创建一个新节点
{
t[++tot]={pos,l,k,d},s.insert({pos,tot});
v[fa[tot]=p].insert({-d,tot});return ;
}
inline void split(int p,ll num)//分裂出来一条链
{
ll pos=t[p].pos,l=t[p].l,k=t[p].k,d=t[p].d;
if(num>1)
{
s.erase({pos,p}),create(fa[p],pos,l,num-1,d);
s.insert({t[p].pos=pos+(num-1)*l,p});
}
if(num<k) create(fa[p],pos+num*l,l,k-num,d);
t[p].k=1;return ;
}
void dfs(int p)//递归子树删除
{
if(t[p].l) T::A(t[p].d,t[p].d+t[p].l-1,-t[p].k);
s.erase({t[p].pos,p});for(P y:v[p]) dfs(y.second);
}
inline void insert(ll x,ll l,ll k)// 1 操作
{
int p=find(x);ll num=(x-t[p].pos)/t[p].l+1;
split(p,num),num=(x-t[p].pos)%t[p].l;
create(p,n+1,l,k,t[p].d+num+1);
T::A(t[p].d+num+1,t[p].d+num+l,k),n+=l*k;return ;
}
inline void erase(ll x)// 2 操作
{
int p=find(x);ll num=(x-t[p].pos)/t[p].l+1;
split(p,num),num=(x-t[p].pos)%t[p].l;
auto it=v[p].begin();
for(P now:v[p])
{
if(-now.first<=t[p].d+num) break;
dfs(now.second),++it;
}
v[p].erase(v[p].begin(),it);
T::A(t[p].d+num,t[p].d+t[p].l-1,-1);
t[p].l=num;return ;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
cin.tie(0),cout.tie(0);
ios::sync_with_stdio(0);
t[1]={1,1,1,1},s.insert({1,1}),T::A(1,1,1);
cin>>m;for(int op;m;--m)
{
cin>>op;ll x,l,k;
if(op==1) cin>>x>>l>>k,insert(x,l,k);
if(op==2) cin>>x,erase(x);
if(op==3) cout<<T::t[1].num<<'\n';
}
return 0;
}