UOJ612 【JOISC2021】饮食区
UOJ612 【JOISC2021】饮食区
重工业做法,常数巨大,随手\(rank\)倒数第一。
吉老师线段树、平衡树
显然没法直接维护,参考【ZJOI2016】大森林的做法,把询问离线下来,在区间的左端点插入,右端点后一个位置删除。
这样维护序列只需要一棵平衡树,但是对于一组询问,我们需要准确定位它的位置。容易发现,操作\(2\)其实不需要真正删除,只需要把之后的询问向右平移即可。我们先利用一棵线段树维护不删除情况下每个位置序列的长度,再用一棵线段树维护带删除情况下每个位置序列的长度,然后在第二棵线段树中查询位置,根据查询到的位置与队尾的相对位置关系,即可推出不删除情况下的询问位置。由于第二棵线段树需要每个位置随时对\(0\)取\(\max\),需要使用吉老师线段树。
\(Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<vector>
#define N 250005
#define IT vector<ask> :: iterator
#define ll long long
using namespace std;
const ll INF=191919191919191919;
int n,m,q,rt,x,y,z,opt,l,r,c,k,cg,ans[N];
ll b;
#define s(p) tr[p].S
#define tag(p) tr[p].Tag
struct node1
{
ll S,Tag;
};
struct sgt1
{
node1 tr[N << 2];
void push_tag(int p,ll y)
{
s(p)+=y,tag(p)+=y;
}
void push_down(int p)
{
push_tag(p << 1,tag(p));
push_tag(p << 1 | 1,tag(p));
tag(p)=0;
}
void modify(int p,int l,int r,int x,int y,ll z)
{
if (l==x && r==y)
{
push_tag(p,z);
return;
}
push_down(p);
int mid(l+r >> 1);
if (y<=mid)
modify(p << 1,l,mid,x,y,z); else
if (x>mid)
modify(p << 1 | 1,mid+1,r,x,y,z); else
{
modify(p << 1,l,mid,x,mid,z);
modify(p << 1 | 1,mid+1,r,mid+1,y,z);
}
}
ll calc(int p,int l,int r,int x)
{
if (l==r)
return s(p);
push_down(p);
int mid(l+r >> 1);
if (x<=mid)
return calc(p << 1,l,mid,x); else
return calc(p << 1 | 1,mid+1,r,x);
}
}s1;
#define mn(p) tr[p].Mn
#define se(p) tr[p].Se
#define tag1(p) tr[p].Tag1
#define tag2(p) tr[p].Tag2
struct node2
{
ll Mn,Se,Tag1,Tag2;
};
struct sgt2
{
node2 tr[N << 2];
void build(int p,int l,int r)
{
mn(p)=0,se(p)=INF;
if (l==r)
return;
int mid(l+r >> 1);
build(p << 1,l,mid);
build(p << 1 | 1,mid+1,r);
}
void push_tag(int p,ll t1,ll t2)
{
mn(p)+=t1,tag1(p)+=t1;
if (se(p)!=INF)
se(p)+=t2,tag2(p)+=t2;
}
void push_down(int p)
{
ll lt(mn(p << 1)),rt(mn(p << 1 | 1));
if (lt<=rt)
push_tag(p << 1,tag1(p),tag2(p)); else
push_tag(p << 1,tag2(p),tag2(p));
if (rt<=lt)
push_tag(p << 1 | 1,tag1(p),tag2(p)); else
push_tag(p << 1 | 1,tag2(p),tag2(p));
tag1(p)=tag2(p)=0;
}
void update(int p)
{
mn(p)=min(mn(p << 1),mn(p << 1 | 1));
if (mn(p << 1)==mn(p << 1 | 1))
se(p)=min(se(p << 1),se(p << 1 | 1));else
if (mn(p)==mn(p << 1))
se(p)=min(se(p << 1),mn(p << 1 | 1)); else
se(p)=min(mn(p << 1),se(p << 1 | 1));
}
void modify1(int p,int l,int r,int x,int y,ll z)
{
if (l==x && r==y)
{
push_tag(p,z,z);
return;
}
push_down(p);
int mid(l+r >> 1);
if (y<=mid)
modify1(p << 1,l,mid,x,y,z); else
if (x>mid)
modify1(p << 1 | 1,mid+1,r,x,y,z); else
{
modify1(p << 1,l,mid,x,mid,z);
modify1(p << 1 | 1,mid+1,r,mid+1,y,z);
}
update(p);
}
void modify2(int p,int l,int r,int x,int y,ll z)
{
if (l==x && r==y)
{
if (mn(p)>=z)
return;
if (l==r)
{
mn(p)=z;
se(p)=INF;
tag1(p)=tag2(p)=0;
} else
if (se(p)>z)
push_tag(p,z-mn(p),0); else
{
push_down(p);
int mid(l+r >> 1);
modify2(p << 1,l,mid,x,mid,z);
modify2(p << 1 | 1,mid+1,r,mid+1,y,z);
update(p);
}
return;
}
push_down(p);
int mid(l+r >> 1);
if (y<=mid)
modify2(p << 1,l,mid,x,y,z); else
if (x>mid)
modify2(p << 1 | 1,mid+1,r,x,y,z); else
{
modify2(p << 1,l,mid,x,mid,z);
modify2(p << 1 | 1,mid+1,r,mid+1,y,z);
}
update(p);
}
ll calc(int p,int l,int r,int x)
{
if (l==r)
return mn(p);
push_down(p);
int mid(l+r >> 1);
if (x<=mid)
return calc(p << 1,l,mid,x); else
return calc(p << 1 | 1,mid+1,r,x);
}
}s2;
struct ask
{
int opt;
ll t;
int c,z;
ask () {}
ask (int o,ll T,int C,int Z=0):opt(o),t(T),c(C),z(Z) {}
};
vector<ask>e[N];
#undef s
#define ls(p) a[p].ch[0]
#define rs(p) a[p].ch[1]
#define rk(p) a[p].Rk
#define tim(p) a[p].Tim
#define val(p) a[p].Val
#define id(p) a[p].Id
#define s(p) a[p].S
struct node3
{
int ch[2],Rk,Tim,Val,Id;
ll S;
};
int ct(0);
struct fhq_treap
{
node3 a[N];
int newnode(int x,int y,int z)
{
++ct;
ls(ct)=rs(ct)=0,rk(ct)=rand(),tim(ct)=x,val(ct)=y,id(ct)=z;
s(ct)=y;
return ct;
}
void update(int p)
{
s(p)=s(ls(p))+s(rs(p))+val(p);
}
void split(int &x,int &y,int rt,int k)
{
if (!rt)
{
x=y=0;
return;
}
if (tim(rt)<=k)
{
x=rt;
split(rs(rt),y,rs(rt),k);
} else
{
y=rt;
split(x,ls(rt),ls(rt),k);
}
update(rt);
}
int combine(int x,int y)
{
if (!x || !y)
return x|y;
if (rk(x)<rk(y))
{
rs(x)=combine(rs(x),y);
update(x);
return x;
} else
{
ls(y)=combine(x,ls(y));
update(y);
return y;
}
}
}T;
int main()
{
srand(time(NULL));
scanf("%d%d%d",&n,&m,&q);
s2.build(1,1,n);
for (int i=1;i<=q;++i)
{
scanf("%d",&opt);
if (opt==1)
{
scanf("%d%d%d%d",&l,&r,&c,&k);
e[l].push_back(ask(1,k,c,i));
e[r+1].push_back(ask(-1,k,c,i));
s1.modify(1,1,n,l,r,k);
s2.modify1(1,1,n,l,r,k);
} else
if (opt==2)
{
scanf("%d%d%d",&l,&r,&k);
s2.modify1(1,1,n,l,r,-k);
s2.modify2(1,1,n,1,n,0);
} else
{
scanf("%d%lld",&c,&b),++cg;
ll g(s2.calc(1,1,n,c));
if (g<b)
ans[cg]=0; else
e[c].push_back(ask(0,s1.calc(1,1,n,c)-(g-b),cg));
}
}
for (int i=1;i<=n;++i)
{
for (IT it=e[i].begin();it!=e[i].end();++it)
{
int opt(it->opt);
ll t(it->t);
int c(it->c),tz(it->z);
if (opt==0)
{
int g(rt);
for (;;)
{
if (T.s(T.ls(g))>=t)
g=T.ls(g); else
if (T.s(T.ls(g))+T.val(g)>=t)
{
ans[c]=T.id(g);
break;
} else
t-=T.s(T.ls(g))+T.val(g),g=T.rs(g);
}
} else
if (opt==1)
{
T.split(x,y,rt,tz);
rt=T.combine(T.combine(x,T.newnode(tz,t,c)),y);
} else
{
T.split(x,y,rt,tz);
T.split(x,z,x,tz-1);
rt=T.combine(x,y);
}
}
}
for (int i=1;i<=cg;++i)
printf("%d\n",ans[i]);
return 0;
}