bzoj3307雨天的尾巴(线段树合并)
来源:互联网 发布:淘宝群怎么能快速拉人 编辑:程序博客网 时间:2024/04/30 13:12
Description
N个点,形成一个树状结构。有M次发放,每次选择两个点x,y
对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成
所有发放后,每个点存放最多的是哪种物品。Input
第一行数字N,M
接下来N-1行,每行两个数字a,b,表示a与b间有一条边
再接下来M行,每行三个数字x,y,z.如题Output
输出有N行
每i行的数字表示第i个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0
我们首先可以树上差分一下贡献,然后线段树自下而上合并就好了. (启发式合并应该更靠谱,然而我动态开点后并不会维护size,维护了反而可能MLE,最后暴力合并一发A了,只是卡了发评测...)
#include <cstdio>#include <iostream>#include <cstring>#define maxn 100005#define maxx 200005#define mem(a,b) memset(a,b,sizeof(a))using namespace std;inline void read(int& x){ char c=getchar();x=0;int y=1; while(c<'0'||c>'9'){if(c=='-') y=-1;c=getchar();} while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); x*=y;}const int VMAX=1e9;inline int m_max(int x,int y){return x>y?x:y;}int n,m,son[maxn],ssum[maxn],top[maxn],fa[maxn],dp[maxn],ans[maxn],num,hea[maxn];struct road{int en,nex;}ro[maxx];inline void add(int x,int y){ro[num].en=y;ro[num].nex=hea[x];hea[x]=num++;}inline void dfs(int x,int y=0){ ssum[x]=1;fa[x]=y;dp[x]=dp[y]+1; for(int i=hea[x];i!=-1;i=ro[i].nex) { int v=ro[i].en; if(v==y) continue; dfs(v,x);ssum[x]+=ssum[v]; if(!son[x]||ssum[son[x]]<ssum[v]) son[x]=v; }}inline void redfs(int x,int y=1){ top[x]=y; if(!son[x]) return; redfs(son[x],y); for(int i=hea[x];i!=-1;i=ro[i].nex) { int v=ro[i].en; if(v!=fa[x]&&v!=son[x]) redfs(v,v); }}inline int flca(int x,int y){ int t1=top[x],t2=top[y]; while(t1!=t2) { if(dp[t1]<dp[t2]) std::swap(t1,t2),std::swap(x,y); x=fa[t1];t1=top[x]; } if(dp[x]>dp[y]) std::swap(x,y); return x;}struct tree{ tree *lch,*rch;int ma; tree():lch(NULL),rch(NULL),ma(0){} inline int mval(){return this?this->ma:0;} inline void mt(){this->ma=m_max(this->lch->mval(),this->rch->mval());}}*root[maxn];inline void update(tree*& now,int x,int l,int r,int z){ if(!now) now=new tree(); if(l==r){now->ma+=z;return;} int mid=l+r>>1; if(x<=mid) update(now->lch,x,l,mid,z); else update(now->rch,x,mid+1,r,z); now->mt();}inline void merge(tree*& x,tree* y,int l,int r){ if(!y) return;if(!x){x=y;return;} if(l==r){x->ma+=y->ma;return;} int mid=l+r>>1; merge(x->lch,y->lch,l,mid);merge(x->rch,y->rch,mid+1,r); x->mt();}inline int dfs4(tree* x,int y,int l,int r){ if(!x) return 0; if(l==r) return l; int mid=l+r>>1; if(x->lch->mval()==y) return dfs4(x->lch,y,l,mid); else return dfs4(x->rch,y,mid+1,r);}inline void dfs3(int x,int y=0){ for(int i=hea[x];i!=-1;i=ro[i].nex) { int v=ro[i].en; if(v==y) continue; dfs3(v,x); merge(root[x],root[v],1,VMAX); } if(root[x]->mval()) ans[x]=dfs4(root[x],root[x]->mval(),1,VMAX);}int main(){ read(n);read(m);int x=0,y=0,z=0;mem(hea,-1); for(int i=1;i<n;++i) { read(x);read(y); add(x,y);add(y,x); } dfs(1);redfs(1); for(int i=1;i<=m;++i) { read(x);read(y);read(z); int tmp=flca(x,y); update(root[x],z,1,VMAX,1); update(root[y],z,1,VMAX,1); update(root[tmp],z,1,VMAX,-1); if(fa[tmp]) update(root[fa[tmp]],z,1,VMAX,-1); } dfs3(1); for(int i=1;i<=n;++i) printf("%d\n",ans[i]); return 0;}
阅读全文
1 0
- [BZOJ3307][线段树合并]雨天的尾巴
- bzoj3307雨天的尾巴(线段树合并)
- 【bzoj3307】雨天的尾巴 线段树+树链剖分
- [BZOJ3307][雨天的尾巴][树链剖分+线段树]
- BZOJ3307 雨天的尾巴 (树链剖分 线段树合并 dfs相关)
- bzoj3307 雨天的尾巴
- [bzoj3307]雨天的尾巴
- BZOJ3307: 雨天的尾巴
- 【BZOJ3307】雨天的尾巴(树链剖分+树上差分+线段树)
- bzoj 3307: 雨天的尾巴 (线段树合并+LCA)
- BZOJ3307——雨天的尾巴
- 【BZOJ3307】雨天的尾巴(权限题)
- BZOJ 3307 雨天的尾巴 线段树
- bzoj 3307: 雨天的尾巴 线段树
- BZOJ 3307: 雨天的尾巴 线段树合并 树上差分
- BZOJ 3307 雨天的尾巴 树上差分+lca+权值线段树合并
- 雨天的尾巴
- [JZOJ3397]雨天的尾巴
- 深度学习装机、系统、环境配置指南--预算15000
- Linux走过的坑(持续更新)
- 部落冲突
- bzoj4264 小C找朋友
- opencv访问元素的几种方法
- bzoj3307雨天的尾巴(线段树合并)
- 烦死人的编码问题
- ctf入门——实验吧
- 算法总结
- Servlet生命周期事件以及事件
- 【笔记】C++排序函数
- Android Camera 开发之基础知识篇
- js封装addClass,removeClass函数
- TreeMap源码解析