清明梦超能力者黄YY[树链剖分+扫描线,线段树合并]

清明梦超能力者黄YY

题目连接

https://www.nowcoder.com/acm/contest/206/I

暂时有两种做法.

算法一

涉及:树链剖分,扫描线

在一个线段的情况下,我们可以把一个染色区间拆成左端点处增加事件,右端点处删除事件.
维护一颗权值线段树.
这样,端点从小到大扫描时,遇到增加事件就在线段树指定位置+1,遇到删除事件就在线段树指定位置-1.

那么要回答一个点的答案只需要扫到这个点的时候,在权值线段树里二分kkk大值即可.

这个搬到了树上,我们照样可以使用扫描线的方法来做.

对于每一个染色区间,将其剖到树链上去,可以剖出最多log(n)log(n)log(n)个小区间.

这些小区间的深度较小的端点加入增加事件,深度较大的端点加入删除事件.

然后对整棵树按照dfndfndfn序列从小到大依次扫描即可,注意扫描的过程中也要维护一颗权值线段树.

算法二

涉及:dfs,权值线段树合并

对于每个询问u,vu,vu,v,应该在uuu处加入增加事件,在vvv处加入增加事件,在lca(u,v)lca(u,v)lca(u,v)处加入删除事件,在faz[lca(u,v)]faz[lca(u,v)]faz[lca(u,v)]处加入删除事件.因此每个询问会产生444个事件.

我们采用dfs的顺序,每个点维护一颗权值线段树,然后后序遍历到达一个节点时候,先将它所有儿子的线段树进行合并,合并完成后,将该点涉及到的增加或删除事件执行到线段树上,此时,该点的权值线段树维护的就是横跨这个节点的所有染色区间.

然后在权值线段树上进行kkk大询问即可得到该点的答案.

算法一.代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define clr(x) memset(x,0,sizeof(x))const int N = 100007;struct edge{int v,nxt;
}es[N<<1];int head[N],tot;void addedge(int u,int v){es[tot].v = v;es[tot].nxt = head[u];head[u] = tot++;
}int faz[N],siz[N],dep[N],top[N],son[N],dfn[N],rnk[N],idx;void dfs1(int u,int fa,int deep) {faz[u] = fa;siz[u] = 1;dep[u] = deep;for(int e = head[u];e != -1;e = es[e].nxt) {int v = es[e].v;if(v == fa) continue;dfs1(v,u,deep+1);siz[u] += siz[v];if(!son[u] || siz[v] > siz[son[u]])son[u] = v;}
}void dfs2(int u,int tp) {dfn[u] = ++idx;rnk[idx] = u;top[u] = tp;if(son[u]) dfs2(son[u],tp);for(int e = head[u];e != -1;e = es[e].nxt) {int v = es[e].v;if(son[u] != v && faz[u] != v)dfs2(v,v);}
}struct node{int val,len;node(int val = 0,int len = 1):val(val),len(len){}
}ns[N<<2];node maintain(node &lch,node &rch) {return node(lch.val + rch.val,lch.len + rch.len);
}void change(int o,int l,int r,int pos,int val) {if(l == r) {ns[o].val += val;return ;}int mid = (l + r) >> 1;if(pos <= mid)change(o<<1,l,mid,pos,val);elsechange(o<<1|1,mid+1,r,pos,val);ns[o] = maintain(ns[o<<1],ns[o<<1|1]);
}int kth(int o,int l,int r,int x) {if(ns[o].val < x) return 0;if(l == r) return l;   int mid = (l + r) >> 1;if(x > ns[o<<1].val)return kth(o<<1|1,mid+1,r,x-ns[o<<1].val);elsereturn kth(o<<1,l,mid,x);
}struct event{int tp,val;event(int tp = 0,int val = 0):tp(tp),val(val){}
};std::vector<event> events[N];int color[N];void modify(int x,int y,int id) {while(top[x] != top[y]) {if(dep[top[x]] < dep[top[y]])std::swap(x,y);events[dfn[x]].push_back(event(-1,id));events[dfn[top[x]]].push_back(event(1,id));x = faz[top[x]];}if(dep[x] < dep[y])std::swap(x,y);events[dfn[x]].push_back(event(-1,id));events[dfn[y]].push_back(event(1,id));
}int n,m,k;
int ans[N];
int main() {memset(head,-1,sizeof(head));std::ios::sync_with_stdio(false);std::cin >> n >> m >> k;rep(i,1,n-1) {int x,y;std::cin >> x >> y;addedge(x,y);addedge(y,x);}dfs1(1,-1,0);dfs2(1,1);rep(i,1,m){int u,v,c;std::cin >> u >> v >> c;color[m+1-i] = c;modify(u,v,m+1-i);}rep(i,1,n) {for(auto e : events[i]){if(e.tp == 1)change(1,1,n,e.val,1);}ans[rnk[i]] = color[kth(1,1,n,k)];for(auto e : events[i]) {if(e.tp == -1)change(1,1,n,e.val,-1);}}rep(i,1,n) {std::cout << ans[i] << " ";}return 0;
}

算法二.代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <assert.h>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define clr(x) memset(x,0,sizeof(x))
#define setinf(x) memset(x,0x3f,sizeof(x))const int N = 100007;
std::vector<int> edge[N];struct node {int sum,lch,rch;node(int sum = 0,int lch = 0,int rch = 0):sum(sum),lch(lch),rch(rch){}
}ns[N*60];
int tot;node maintain(node &lch,node &rch,int l,int r) {return node(lch.sum+rch.sum,l,r);
}void insert(int& o,int l,int r,int pos,int add) {if(!o)o = ++tot;if(l == r) {ns[o].sum += add;return ;}int mid = (l + r) >> 1;if(pos <= mid)insert(ns[o].lch,l,mid,pos,add);elseinsert(ns[o].rch,mid+1,r,pos,add);ns[o] = maintain(ns[ns[o].lch],ns[ns[o].rch],ns[o].lch,ns[o].rch);
}node query(int o,int l,int r,int ql,int qr) {if(o == 0) return ns[0];if(ql <= l && r <= qr)return ns[o];if(r < ql || qr < l)return ns[0];int mid = (l + r) >> 1;node lch = query(ns[o].lch,l,mid,ql,qr);node rch = query(ns[o].rch,mid+1,r,ql,qr);return maintain(lch,rch,0,0);
}int merge(int a,int b) {if(!a) return b;if(!b) return a;int o = ++tot;assert(o < N*60);ns[o].sum = ns[a].sum + ns[b].sum;ns[o].lch = merge(ns[a].lch,ns[b].lch);ns[o].rch = merge(ns[a].rch,ns[b].rch);return o;
}int ans[N],color[N];int faz[N],siz[N],top[N],dep[N],dfn[N],son[N],idx;void dfs1(int u,int fa,int deep) {faz[u] = fa;dep[u] = deep;siz[u] = 1;for(auto v : edge[u]) {if(v == fa) continue;dfs1(v,u,deep+1);siz[u] += siz[v];if(siz[son[u]] < siz[v])son[u] = v;}
}void dfs2(int u,int tp) {dfn[u] = ++idx;top[u] = tp;if(son[u])dfs2(son[u],tp);for(auto v : edge[u]) {if(v == faz[u] || v == son[u]) continue;dfs2(v,v);}
}int lca(int u,int v) {while(top[u] != top[v]) {if(dep[top[u]] < dep[top[v]])v = faz[top[v]];elseu = faz[top[u]];}return dep[u] > dep[v] ? v : u;
}int kth(int o,int l,int r,int k) {if(!o || ns[o].sum < k)return 0;if(l == r) return l;int mid = (l + r) >> 1;if(k <= ns[ns[o].lch].sum)return kth(ns[o].lch,l,mid,k);elsereturn kth(ns[o].rch,mid+1,r,k-ns[ns[o].lch].sum);
}int n,m,k;
int root[N];
std::vector<int> add[N],dec[N];
void dfs(int u,int fa) {for(auto v : edge[u]) {if(v == fa) continue;dfs(v,u);root[u] = merge(root[u],root[v]);}for(auto x : dec[u]){insert(root[u],1,n,x,-1);}for(auto y : add[u]){insert(root[u],1,n,y,1);}ans[u] = color[kth(root[u],1,n,k)];
}int main() {std::ios::sync_with_stdio(false);std::cin >> n >> m >> k;rep(i,1,n-1) {int u,v;std::cin >> u >> v;edge[u].push_back(v);edge[v].push_back(u);}dfs1(1,0,0);dfs2(1,1);for(int i = m;i >= 1;--i) {int u,v;std::cin >> u >> v >> color[i];add[u].push_back(i);add[v].push_back(i);int _lca = lca(u,v);dec[_lca].push_back(i);dec[faz[_lca]].push_back(i);}dfs(1,0);rep(i,1,n) {std::cout << ans[i] << " ";}std::cout << std::endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初一模拟赛总结(3.23)

成绩&#xff1a; rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3T4T4T4111lyflyflyf300300300100100100100100100100100100000222wjjwjjwjj290290290100100100100100100909090000333hkyhkyhky270270270100100100100100100707070000444fyfyfy24024024010010010010…

CF1110E-Magic Stones【结论题,差分】

正题 题目链接:https://www.luogu.com.cn/problem/CF1110E 题目大意 给出一个序列cic_ici​和一个序列tit_iti​。每次操作可以将cici−1ci1−ci(1<i<n)c_ic_{i-1}c_{i1}-c_i(1<i<n)ci​ci−1​ci1​−ci​(1<i<n) 解题思路 首先要求c1t1,cntnc_1t_1,c_nt…

好代码是管出来的——C#的代码规范

代码是软件开发过程的产物&#xff0c;代码的作用是通过编译器编译后运行&#xff0c;达到预期的效果(功能、稳定性、安全性等等)&#xff0c;而另外一个重要作用是给人阅读。对于机器来说只要代码正确就能够正确的运行程序&#xff0c;但是人不同&#xff0c;如果代码编写混乱…

【图论】【高精】产生数(ssl 1021/ luogu 1037)

产生数 ssl 1021 luogu 1037 题目大意&#xff1a; 有一个数&#xff0c;可以使某些数字变成相对应的数字&#xff0c;问有多少种变法 原题&#xff1a; Description 给出一个整数 n&#xff08;n<10^30) 和 k 个变换规则&#xff08;k<15&#xff09;。   规则…

P3224-[HNOI2012]永无乡【平衡树,启发式合并】

正题 题目链接:https://www.luogu.com.cn/problem/P3224 题目大意 nnn个点&#xff0c;每次可以连接两个点和询问一个点所在联通块中第kkk大的数。 解题思路 我们发现可以启发式合并&#xff0c;对于每个联通块维护一个线段树&#xff0c;然后每次合并时将小的暴力丢入大的平…

牛客国庆集训派对Day6

牛客国庆集训派对Day6 以下是我个人题解,出题人题解附带在最后 A.Birthday 费用流裸题,只要注意到135...2k−1k2135...2k-1 k^2135...2k−1k2即可已做这道题了. 其他的地方连边都很方便.每一个区域向汇点连很多条容量为111的边,但费用分别是1,3,5,...,2k−11,3,5,...,2k-11…

.NET Core微服务之基于IdentityServer建立授权与验证服务(续)

上一篇《.NET Core微服务之基于IdentityServer建立授权与验证服务》我们基于IdentityServer4建立了一个AuthorizationServer&#xff0c;并且继承了QuickStartUI&#xff0c;能够成功获取Token了。这一篇我们了解下如何集成API Service和MVC Web Application。一、集成API Serv…

P4587-[FJOI2016]神秘数【主席树】

正题 题目链接:https://www.luogu.com.cn/problem/P4587 题目大意 nnn个数&#xff0c;每次选择一个区间&#xff0c;然后询问这个区间的子集和所不能表示的最小的正整数。 解题思路 假设我们从小到大加入数字&#xff0c;我们发现如果这个数不是111显然这个区间内至少有一个…

【图论】【Floyed】舞会邀请(CODE[VS] 2604)

舞会邀请 CODE[VS] 2604 题目大意&#xff1a; Smart要叫一些人开Party&#xff0c;每个人可以通知一部分人&#xff0c;Smart去通知一些人&#xff0c;再让这些人去通知其他人&#xff0c;问Smart最少通知几个人&#xff0c;可以使全部人都被通知到 原题&#xff1a; 题目…

ASP.NET Core 2.1 : 十一. 如何在后台运行一个任务

在大部分程序中一般都会需要用到后台任务&#xff0c; 比如定时更新缓存或更新某些状态。一、应用场景以调用微信公众号的Api为例&#xff0c; 经常会用到access_token&#xff0c;官方文档这样描述&#xff1a;“是公众号的全局唯一接口调用凭据&#xff0c;有效期目前为2个小…

【Floyed】工厂的烦恼(ssl 1762)

工厂的烦恼 ssl 1762 题目大意&#xff1a; 求一个图中最长的路线的长度 原题&#xff1a; Description 某工厂发现厂里的机器在生产产品时要消耗大量的原材料&#xff0c;也就是说&#xff0c;有大量的原材料变成了废物。因此厂里想找出消耗原材料最大的一条生产线路进行…

P3899-[湖南集训]谈笑风生【主席树】

正题 题目链接:https://www.luogu.com.cn/problem/P3899 题目大意 给出nnn个点的一棵有根树&#xff0c;每次询问一个(p,k)(p,k)(p,k)&#xff0c;求有多少个点对(b,c)(b,c)(b,c)满足 ppp和bbb是ccc的祖先bbb与ppp的距离不超过kkk 蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤…

好代码是管出来的——.Net中的代码规范工具及使用

上一篇文章好代码是管出来的——C#的代码规范介绍了编码标准中一些常用的工具&#xff0c;本篇就具体来介绍如何使用它们来完成代码管理。  本文主要内容有&#xff1a;Roslyn简介开发基于Roslyn的代码分析器常用的基于Roslyn的代码分析器在.Net Framework项目中使用代码分析…

NCPC2018 D.Delivery Delays[二分答案+DP check]

Delivery Delays 题意 100010001000个点,500050005000条边的无向图,披萨店在111号店.100010001000份披萨订单,每个订单有下单时间,送达地点,披萨制作出来的时间.你是快递员初始在111号点,每次可以拿无穷多披萨,送完以后返回111号点继续送,送餐的时候要求按照下单顺序送达,求等…

P6046-纯粹容器【数学期望,组合数】

正题 题目链接:https://www.luogu.com.cn/problem/P6046 题目大意 nnn个数&#xff0c;每次选择两个相邻的数删除小的那个&#xff0c;求每个数期望存活轮数。 解题思路 相当于一条链每次缩掉一条边&#xff0c;我们发现其实每个点只需要考虑左右第一个比它大的就好了。定义…

【dfs】病毒(jzoj 1284)

病毒 题目大意&#xff1a; 有n&#xff08;1<n<1000&#xff09;头奶牛&#xff0c;d&#xff08;1<d<15&#xff09;种病毒&#xff0c;每头奶牛身上有可能有很多种病毒病毒&#xff0c;每头奶牛挤出的牛奶是混在一起放的&#xff0c;问最多可以挤多少头奶牛的…

探讨.NET Core的未来

本文要点与传统的.NET Framework相比&#xff0c;.NET Core平台具有显著的性能优势。.NET Core在Microsoft平台之外也广为采用&#xff0c;并受益于强大的社区参与。.NET Core在设计上采用以服务器为中心&#xff0c;而非聚焦于Windows。.NET Core开发受益于这种设计。.NET Cor…

HDU5985 Lucky Conins 概率题

Lucky Conins 题意 最多共101010种硬币,所有的硬币之和不超过100000100000100000,每次将所有的硬币抛出,第iii中硬币正面朝上的概率为pip_ipi​,将反面朝上的硬币移除掉.直至最后剩一种硬币或没有硬币则停止.若最后剩余一种硬币,则称这种硬币是幸运的,求每种硬币的幸运概率. …

P6619-[省选联考2020A/B卷]冰火战士【树状数组二分】

正题 题目链接:https://www.luogu.com.cn/problem/P6619 题目大意 有火系战士和冰系战士有一个温度和一个战斗力&#xff0c;每次加入或删除一个战士&#xff0c;要求一个最大的kkk使得温度不低于kkk的火系战士战斗力和温度不高于kkk的冰系战士战斗力和的最小值最大。 解题思…

【数论】分数拆分

分数拆分 题目大意&#xff1a; 给出一个数k&#xff0c;问满足1/k1/x1/y且x>y的x,y有多少对 原题&#xff1a; 解题思路&#xff1a; 首先1k1x1y\frac{1}{k}\frac{1}{x}\frac{1}{y}k1​x1​y1​,变式为1k−1y1x\frac{1}{k}-\frac{1}{y}\frac{1}{x}k1​−y1​x1​,然后再…