HDU5840 (分块+树链剖分)
Problem This world need more Zhu
题目大意
给一颗n个点的有点权的树,有m个询问,对于每个询问u,v,k,首先将点u到点v的最短路径上的所有点按顺序编号,u的编号为1,求树链上所有点的新编号cnt满足cnt%k==0的点的权值的最大值。
n,m,k<=10^5
解题分析
根据k的大小分成两部分处理。原问题可转化为 deep[i] % k = a / b 。
对于k较大的,直接暴力,按照dfs序用一个栈记录下所经过的点,对于每个询问的点不停往上爬。
对于k较小的,将询问按照k分类。对于每一种k,将所有点按照dep[i] % k分类,将每个点树链剖分后hash下来的坐标再按照dep[i] % k映射到一起,用线段树进行维护。
每次查询deep[i] % k = a 时,相当于在某个区间查询最大值。
参考程序
- #include <map>
- #include <set>
- #include <stack>
- #include <queue>
- #include <cmath>
- #include <ctime>
- #include <string>
- #include <vector>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <cassert>
- #include <iostream>
- #include <algorithm>
- #pragma comment(linker,"/STACK:102400000,102400000")
- using namespace std;
- #define N 100008
- #define LL long long
- #define lson l,m,rt<<1
- #define rson m+1,r,rt<<1|1
- #define clr(x,v) memset(x,v,sizeof(x));
- #define bitcnt(x) __builtin_popcount(x)
- #define rep(x,y,z) for (int x=y;x<=z;x++)
- #define repd(x,y,z) for (int x=y;x>=z;x--)
- const int mo = ;
- const int inf = 0x3f3f3f3f;
- const int INF = ;
- /**************************************************************************/
- int T,n,m,k,sum,block,stop,cq2,tmp,label;
- int lt[N],a[N],dep[N],st[N],ans[N],size[N],son[N],rk[N],w[N],top[N],mx[N<<],cl[N],cr[N],fuck[N];;
- int f[N][];
- struct line{
- int u,v,nt;
- }eg[N*];
- struct que{
- int u,v,lca,k,id,flag;
- };
- vector <que> q1[N],q2[N];
- void add(int u,int v){
- eg[++sum]=(line){u,v,lt[u]};
- lt[u]=sum;
- }
- void init(){
- clr(lt,); clr(ans,);
- sum=; tmp=;
- }
- void dfs(int u,int fa){
- f[u][]=fa; dep[u]=dep[fa]+; size[u]=; son[u]=;
- for (int i=lt[u];i;i=eg[i].nt){
- int v=eg[i].v;
- if (v==fa) continue;
- dfs(v,u);
- size[u]+=size[v];
- if (size[v]>size[son[u]]) son[u]=v;
- }
- }
- void dfs_2(int u,int tp){
- top[u]=tp; w[u]=++tmp; rk[tmp]=u;
- if (son[u]) dfs_2(son[u],tp);
- for (int i=lt[u];i;i=eg[i].nt){
- int v=eg[i].v;
- if (v==f[u][] || v==son[u]) continue;
- dfs_2(v,v);
- }
- }
- int lca(int x,int y){
- if (dep[x]<dep[y]) swap(x,y);
- int d=dep[x]-dep[y];
- repd(i,,)
- if (d & (<<i)) x=f[x][i];
- if (x==y) return x;
- repd(i,,)
- if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
- return f[x][];
- }
- void work_1(int u){
- st[++stop]=u;
- for (int i=;i<q1[u].size();i++){
- int v=q1[u][i].v,x=q1[u][i].lca,k=q1[u][i].k,id=q1[u][i].id,flag=q1[u][i].flag;
- if (flag)
- {
- int tmp=stop-k+;
- while (tmp>= && dep[st[tmp]]>=dep[x]){
- ans[id]=max(ans[id],a[st[tmp]]);
- tmp-=k;
- }
- }
- else
- {
- int tmp=dep[x]+ k - (dep[v]-dep[x]+) % k ;
- while (tmp<=stop && dep[st[tmp]]<=dep[u]){
- ans[id]=max(ans[id],a[st[tmp]]);
- tmp+=k;
- }
- }
- }
- for (int i=lt[u];i;i=eg[i].nt){
- int v=eg[i].v;
- if (v==f[u][]) continue;
- work_1(v);
- }
- st[stop--]=;
- }
- int query(int L,int R,int l,int r,int rt){
- if (L<=l && r<=R){
- return mx[rt];
- }
- int m=(l+r)>>;
- int res=;
- if (L <= m) res=max(res,query(L,R,lson));
- if (m < R) res=max(res,query(L,R,rson));
- return res;
- }
- void build(int l,int r,int rt){
- mx[rt]=;
- if (l==r){
- mx[rt]=a[rk[fuck[l]]];
- return;
- }
- int m=(l+r)>>;
- build(lson);
- build(rson);
- mx[rt]=max(mx[rt<<],mx[rt<<|]);
- }
- int calc(int L, int R, int k) {
- int l = lower_bound(fuck + cl[k], fuck + cr[k] + , L) - fuck;
- int r = upper_bound(fuck + cl[k], fuck + cr[k] + , R) - fuck - ;
- return l <= r ? query(l,r,,n,) : ;
- }
- void find(int tp,int x,int cl,int id){
- while (top[x]!=top[tp]){
- ans[id]=max(ans[id],calc(w[top[x]],w[x],cl));
- x=f[top[x]][];
- }
- ans[id]=max(ans[id],calc(w[tp],w[x],cl));
- }
- vector <int> E[N];
- void work_2(int k){
- rep(i,,k) E[i].clear();
- rep(i,,n) E[(dep[rk[i]]) % k].push_back(i);
- label=;
- rep(i,,k-){
- cl[i]=label+;
- for (int j=;j<E[i].size();j++)
- fuck[++label]=E[i][j];
- cr[i]=label;
- }
- build(,n,);
- for (int i=;i<q2[k].size();i++){
- int u=q2[k][i].u,v=q2[k][i].v,x=q2[k][i].lca,id=q2[k][i].id;
- int tmp1=(dep[x]+(dep[u]-dep[x]+) % k) % k;
- int tmp2=(dep[x]+k-(dep[u]-dep[x]+) % k) % k;
- find(x,u,tmp1,id);
- find(x,v,tmp2,id);
- }
- }
- int main(){
- int cas=;
- scanf("%d",&T);
- while (T--){
- printf("Case #%d:\n",++cas );
- init();
- scanf("%d%d",&n,&m);
- rep(i,,n) scanf("%d",&a[i]);
- rep(i,,n-){
- int u,v;
- scanf("%d%d",&u,&v);
- add(u,v); add(v,u);
- }
- dfs(,);
- dfs_2(,);
- rep(j,,)
- rep(i,,n)
- f[i][j]=f[f[i][j-]][j-];
- block=;
- cq2=;
- rep(i,,n) q1[i].clear();
- rep(i,,n) q2[i].clear();
- rep(i,,m){
- int u,v,k;
- scanf("%d%d%d",&u,&v,&k);
- int x=lca(u,v);
- if (k>block)
- {
- q1[u].push_back((que){u,v,x,k,i,});
- q1[v].push_back((que){v,u,x,k,i,});
- }
- else
- {
- q2[k].push_back((que){u,v,x,k,i,});
- }
- }
- work_1();
- rep(i,,block) if (q2[i].size()) work_2(i);
- rep(i,,m) printf("%d\n",ans[i]);
- }
- }
HDU5840 (分块+树链剖分)的更多相关文章
- HDU5840(SummerTrainingDay08-B 树链剖分+分块)
This world need more Zhu Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- 【UOJ#435】【集训队作业2018】Simple Tree 分块+树链剖分
题目大意: 有一棵有根树,根为 1 ,点有点权.现在有 m 次操作,操作有 3 种:1 x y w ,将 x 到 y 的路径上的点点权加上 w (其中 w=±1w=±1 ):2 x y ,询问在 x ...
- UOJ#435. 【集训队作业2018】Simple Tree 树链剖分,分块
原文链接www.cnblogs.com/zhouzhendong/p/UOJ435.html 前言 分块题果然是我这种蒟蒻写不动的.由于种种原因,我写代码的时候打错了很多东西,最致命的是数组开小了.* ...
- 【块状树】【树链剖分】bzoj1036 [ZJOI2008]树的统计Count
很早之前用树链剖分写过,但是代码太长太难写,省选现场就写错了. #include<cstdio> #include<algorithm> #include<cstring ...
- jzoj5987. 【WC2019模拟2019.1.4】仙人掌毒题 (树链剖分+概率期望+容斥)
题面 题解 又一道全场切的题目我连题目都没看懂--细节真多-- 先考虑怎么维护仙人掌.在线可以用LCT,或者像我代码里先离线,并按时间求出一棵最小生成树(或者一个森林),然后树链剖分.如果一条边不是生 ...
- 【树链剖分 差分】bzoj3626: [LNOI2014]LCA
把LCA深度转化的那一步还是挺妙的.之后就是差分加大力数据结构了. Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- BZOJ 1984: 月下“毛景树” [树链剖分 边权]
1984: 月下“毛景树” Time Limit: 20 Sec Memory Limit: 64 MBSubmit: 1728 Solved: 531[Submit][Status][Discu ...
- codevs 1228 苹果树 树链剖分讲解
题目:codevs 1228 苹果树 链接:http://codevs.cn/problem/1228/ 看了这么多树链剖分的解释,几个小时后总算把树链剖分弄懂了. 树链剖分的功能:快速修改,查询树上 ...
随机推荐
- Electron-使用Electron开发第一个应用
使用Electron开发第一个应用 Electron 应用的目录结构如下: app/ ├── package.json ├── main.js └── index.html 新建一个app文件夹 将这 ...
- Topcoder SRM570 900 CurvyonRails
题意:给定一个网格,一些格子是障碍不用管,剩余的格子是城市,你可以修建铁路,铁路的形状可以是直的或者弯的,也就是说可以以这个点为节点连接它四联通的其中两个方块.要求用一个或多个环来覆盖所有城市.对于有 ...
- java.lang.UnsupportedClassVersionError出错
代码出错如下:java.lang.UnsupportedClassVersionError: cn/itcast/mybatis/first/MybatisFirst : Unsupported ma ...
- jQuery中animate的height的自适应
可以用 animate() 方法几乎可以操作大部分CSS 属性,但其属性的值不能为字符串,很多人都遇到过这个问题. 例如:获取一个元素自适应时的高,但el.animate({height:‘aut ...
- 针对不同浏览器,CSS如何写
我们在开发DIV+CSS页面时候常常会遇到开发出的网页的一些地方在各大浏览器比如微软IE6.微软IE7.微软IE8.火狐浏览器.谷歌浏览器有一些不同,如宽度.高度等地方有相差误.IE6比较老的版本浏览 ...
- Android 取源码时 error: could not verify the tag 'v1.12.4'的解决
原帖地址http://forum.xda-developers.com/showthread.php?p=46100064也没说啥原因 repo init -u git://github.com/Cy ...
- mac idea中 maven项目添加的时候没有java文件
file --other setting --maven 选中第二项即可 apply下
- JS数组中every(),filter(),forEach(),map(),some()方法学习笔记!
ES5中定义了五种数组的迭代方法:every(),filter(),forEach(),map(),some(). 每个方法都接受两个参数:要在每一项运行的函数(必选)和运行该函数的作用域的对象-影响 ...
- jQuery---中的动画
show():$('p').show(); show(1000) 里面加参数会让元素在显示的时候动起来 hide():$('p').hide(); hide(1000) 里面加参数让元素在隐藏的时候动 ...
- JAVAFX纯手写布局
主页面效果: 第一栏的效果: 工程目录: package MessageBean; /** * * @author novo */ public class Message { private Str ...