2024-03-10
2024-03-10
雨天的尾巴(线段树合并)
- 每个点建动态开点权值线段树,把每棵树的根记到
跟 gyx 学长学的线段树小窍门%%%
- 在
结构体中重载 号代替 函数类型设置为 方便合并答案
第 2 条在这题里面没有用到
关于第一条
加法返回的结果可能使结构体中某些量被覆盖而丢失原来存的数
算上这次我已经因为这个寄了两回了🤣
第二条还是可以用用的,关于第一条……乖乖写 update 吧🤔
- 路径修改转化为树上差分
x
到y
路径上所有点+1
转化为
x, y
位置+1
,lca(x,y),fa[lca(x,y)]
位置-1
lca 可以用 倍增/树链剖分 实现
- 处理完修改 一遍 dfs 进行线段树合并
mergetr 传参数的时候传成 u, v 了,感谢 ztx 指出错误%%%
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1e5+10;
int MX;
struct OPT {
int x,y,k;
}op[N];
struct Node {
int ls,rs;
int mxn,mxk;
}tr[N*60];
int root[N];
int idnode=0;
void update(int u) {
if(tr[tr[u].ls].mxn>=tr[tr[u].rs].mxn)
tr[u].mxn=tr[tr[u].ls].mxn,tr[u].mxk=tr[tr[u].ls].mxk;
else tr[u].mxn=tr[tr[u].rs].mxn,tr[u].mxk=tr[tr[u].rs].mxk;
}
int update(int u,int lft,int rgh,int k,int f) {
if(!u) u=++idnode;
if(lft==rgh) {
tr[u].mxn+=f,tr[u].mxk=lft;
return u;
}
int mid=lft+rgh>>1;
if(k<=mid) tr[u].ls=update(tr[u].ls,lft,mid,k,f);
else tr[u].rs=update(tr[u].rs,mid+1,rgh,k,f);
update(u);
return u;
}
int mergetr(int u,int v,int lft,int rgh) {
if(!u||!v) return u+v;
if(lft==rgh) {
tr[u].mxn+=tr[v].mxn,tr[u].mxk=lft;
return u;
}
int mid=lft+rgh>>1;
tr[u].ls=mergetr(tr[u].ls,tr[v].ls,lft,mid);
tr[u].rs=mergetr(tr[u].rs,tr[v].rs,mid+1,rgh);
update(u);
return u;
}
int n,m;
int hd[N],edg[N*2],nxt[N*2],idx;
void adde(int u,int v) {
edg[idx]=v,nxt[idx]=hd[u],hd[u]=idx++;
}
int fa[N],sn[N];
int dep[N],top[N],siz[N];
void dfs1(int u,int father) {
fa[u]=father,siz[u]=1,dep[u]=dep[father]+1;
for(int i=hd[u];~i;i=nxt[i]) {
int v=edg[i];
if(v==father) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[sn[u]]) sn[u]=v;
}
}
void dfs2(int u,int tp) {
top[u]=tp;
if(!sn[u]) return;
dfs2(sn[u],tp);
for(int i=hd[u];~i;i=nxt[i]) {
int v=edg[i];
if(v==fa[u]||v==sn[u]) continue;
dfs2(v,v);
}
}
int lca(int u,int v) {
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
int ans[N];
void merge_dfs(int u) {
for(int i=hd[u];~i;i=nxt[i]) {
int v=edg[i];
if(v==fa[u]) continue;
merge_dfs(v);
root[u]=mergetr(root[u],root[v],1,MX);
}
if(tr[root[u]].mxn) ans[u]=tr[root[u]].mxk;
}
int main() {
memset(hd,-1,sizeof(hd));
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++) {
int u,v;
scanf("%d%d",&u,&v);
adde(u,v),adde(v,u);
}
dfs1(1,0);
dfs2(1,1);
for(int i=1;i<=m;i++) {
scanf("%d%d%d",&op[i].x,&op[i].y,&op[i].k);
MX=max(MX,op[i].k);
}
for(int i=1;i<=m;i++) {
int x=op[i].x,y=op[i].y,k=op[i].k;
int z=lca(x,y),w=fa[z];
root[x]=update(root[x],1,MX,k,1);
root[y]=update(root[y],1,MX,k,1);
root[z]=update(root[z],1,MX,k,-1);
root[w]=update(root[w],1,MX,k,-1);
}
merge_dfs(1);
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}
Riddle
前天看到 bpc 在做的题%%%
2-SAT,前几天比赛前打板子刚复习了一下,练一练
还没做出来,出学校hh,回来再写
upd:调出来了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」