【DS】CF696E ...Wait for it...
考虑每个数只会删一次,意味着我们暴力找跟暴力删复杂度正确。
即问题变为
每个点是一个集合
-
对于路径 \((u,v)\) 找每个集合的元素的最小值
-
删去这个最小值
-
子树加
考虑树剖,集合的话可以用 vector+启发式合并
之类的去维护线段树中一个点的区间集合并集,但是我们只需要维护最小值,于是对于线段树上的点记录最小值即可。
考虑删除,找到后暴力删。
对于线段树的标记,我们只需要正常下放,在删除的时候计算出最小值加了多少,把这些所加的保留即可。
注意时空常数。
#include
#define ll long long
#define KG putchar(' ')
using namespace std;
// 树剖+线段树 维护小根堆
#define N (int)(2e5+5)
#define inf (ll)(2e18)
#define min(A,B) (Aq[N];
struct DAT {
ll x; int id,pos;
DAT(ll xx=inf,int idd=(int)(1e9),int poss=0) {
x=xx; id=idd; pos=poss;
}
bool operator < (const DAT &rhs) const {
return x==rhs.x?id>1;
build(ls,l,mid); build(rs,mid+1,r);
push_up(cur);
}
void update(int cur,int l,int r,int cl,int cr,ll x) {
if(cl<=l&&r<=cr) {
T[cur].tag+=x; T[cur].mi.x+=x; return ;
}
push_down(cur);
int mid=(l+r)>>1;
if(cl<=mid) update(ls,l,mid,cl,cr,x);
if(cr>mid) update(rs,mid+1,r,cl,cr,x);
push_up(cur);
}
DAT query(int cur,int l,int r,int cl,int cr) {
if(cl<=l&&r<=cr) {
// cout<<-T[cur].mi.x+T[cur].tag<<" "<<-T[cur].mi.id<>1;
if(cr<=mid) return query(ls,l,mid,cl,cr);
if(cl>mid) return query(rs,mid+1,r,cl,cr);
return min(query(ls,l,mid,cl,cr),query(rs,mid+1,r,cl,cr));
push_up(cur);
}
void del(int cur,int l,int r,int pos) {
if(l==r) {
ll qwq=q[rk[l]].front(); q[rk[l]].pop();
if(q[rk[l]].empty()) T[cur].mi=DAT(inf,(int)(1e9),0);
else {
qwq=T[cur].mi.x-qwq+q[rk[l]].front();
T[cur].mi=DAT(qwq,q[rk[l]].front(),l);
}
return ;
}
push_down(cur);
int mid=(l+r)>>1;
if(pos<=mid) del(ls,l,mid,pos);
else del(rs,mid+1,r,pos);
push_up(cur);
}
}
void add_edge(int x,int y) {
e[++cnt].nex=hea[x]; e[cnt].to=y; hea[x]=cnt;
}
void dfs1(int x,int ff) {
fa[x]=ff; dep[x]=dep[ff]+1; sz[x]=1;
for(int i=hea[x];i;i=e[i].nex) {
int y=e[i].to; if(y==ff) continue;
dfs1(y,x); sz[x]+=sz[y];
if(sz[y]>sz[son[x]]) son[x]=y;
}
}
void dfs2(int x,int tpp) {
tp[x]=tpp; id[x]=++tot; rk[tot]=x;
if(son[x]) dfs2(son[x],tpp);
for(int i=hea[x];i;i=e[i].nex) {
int y=e[i].to;
if(y==son[x]||y==fa[x]) continue;
dfs2(y,y);
}
}
vectorans;
void solve(int fx,int fy,int z) {
ans.clear();
while(z--) {
int x=fx,y=fy; DAT res=DAT(inf,(int)(1e9),0);
while(tp[x]!=tp[y]) {
if(dep[tp[x]]id[y]) swap(x,y);
res=min(res,xgf::query(1,1,n,id[x],id[y]));
// cout<=inf) break;
ans.push_back(res.id);
xgf::del(1,1,n,res.pos);
}
cout<>n>>m>>Q;
for(int i=1;i>x>>y;
add_edge(x,y); add_edge(y,x);
}
for(int i=1;i<=m;i++) {
cin>>x;
q[x].push(i);
}
dfs1(1,0); dfs2(1,0); xgf::build(1,1,n);
while(Q--) {
cin>>op>>x>>y;
if(op==1) {
cin>>z;
solve(x,y,z);
} else {
xgf::update(1,1,n,id[x],id[x]+sz[x]-1,1ll*y);
}
}
return 0;
}