题意

https://loj.ac/problem/2135

思路

首先要明确一点,答案分布是有单调性的。什么意思呢?假设我们的答案在 \(u\) 节点,\((u,v)\) 之间有一条边且 \(u\) 离答案所在的点更近,那么 \(u\) 节点作为答案一定不比在 \(v\) 节点作答案劣。从链的角度分析在拓展到树上会比较好理解这个性质。

那么如果树是一棵完全二叉树,就可以 \(\log n\) 的回答了。从根节点向下跳,每次如果找到一个 \(\displaystyle2*sum[u]\geq tot\) (\(sum[u]\) 为 \(u\) 子树点权之和, \(tot\) 为整张图点权之和)的节点,就说明存在一个更优或不劣的答案,就往这个方向跳,直到不能跳为止。更新时直接暴力修改父亲,没什么可说的。

虽然这棵树不一定是完全二叉树,但是这棵树的“分治树”高度一定是不超过 \(\log n\) 的(我个人不习惯使用“分治树”的概念,而将点分治理解为重心管辖区域这样的概念)。那么就对这棵树进行点分,存下每个数对应的每一层重心对应容器的标号,到它的距离,以及是容是斥。此题的每层重心的容器就是两个变量 \(Sum,sum\) ,其中 \(Sum\) 表示此重心管辖区域权值乘距离总和,\(sum\) 表示权值总和。那么对于 \(u\) 一层重心对应容器编号为 \(id\) ,距离 \(dis\) ,容斥系数为 \(s\) ,产生贡献即为 \(s(Sum[id]+dis\cdot sum[id])\) 。那么就能 \(O(\log n)\) 的询问取某个点的答案是多少了。

修改仍为暴力修改,没什么好说的。

关键在于回答询问,我们从整张图的重心 \(u​\) 开始跳,这个重心 \(u​\) 将树劈成了若干个连通块(题目有条件,最多 \(20​\) 个),对于其中一个连通块,我们设 \(v​\) 在这个连通块内且与 \(u​\) 有边。我们查询选 \(v​\) 的得到的答案,如果小于等于 \(u​\) 的答案,那么就要跳了。妙的是这里跳的是这个连通块的重心 \(w​\),这样就可以保证复杂度了。所以,在点分的时候就要顺便把每个层重心 \(u​\) 的下层重心 \(w​\) ,以及对应的 \(v​\) 存下来。复杂度 \(O(20 \cdot n\log ^2n)​\) ,还是挺飘的。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
using namespace std;
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
const int N=1e5+5;
template<const int maxn,const int maxm>struct Linked_list
{
int head[maxn],to[maxm],nxt[maxm],cost[maxm],tot;
Linked_list(){clear();}
void clear(){memset(head,-1,sizeof(head));tot=0;}
void add(int u,int v,int w){to[++tot]=v,cost[tot]=w,nxt[tot]=head[u],head[u]=tot;}
#define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
Linked_list<N,N<<1>G,H;
ll sum[N*2],Sum[N*2];int Sc;
int lv[N],Sid[N][40];ll dis[N][40];bool sgn[N][40];
int sz[N];bool mark[N];
int n,q; void CFS(int u,int f,int tot,int &C,int &Mi)
{
sz[u]=1;int res=0;
EOR(i,G,u)
{
int v=G.to[i];
if(v==f||mark[v])continue;
CFS(v,u,tot,C,Mi);
sz[u]+=sz[v];
res=max(res,sz[v]);
}
res=max(res,tot-sz[u]);
if(chk_min(Mi,res))C=u;
}
void dfs_init(int u,int f,ll D,bool s)
{
Sid[u][++lv[u]]=Sc,dis[u][lv[u]]=D,sgn[u][lv[u]]=s;
EOR(i,G,u)
{
int v=G.to[i],w=G.cost[i];
if(v==f||mark[v])continue;
dfs_init(v,u,D+w,s);
}
}
void dac(int u,int f,int tot)
{
int rt=u,Mi=1e9;
CFS(u,0,tot,u,Mi);
if(f)H.add(f,u,rt);
mark[u]=1;
Sc++,dfs_init(u,0,0,1); EOR(i,G,u)
{
int v=G.to[i],w=G.cost[i];
if(mark[v])continue;
Sc++,dfs_init(v,u,w,0);
dac(v,u,sz[u]>sz[v]?sz[v]:tot-sz[u]);
}
}
void update(int u,int val)
{
FOR(i,1,lv[u])
{
int id=Sid[u][i];ll d=dis[u][i];
sum[id]+=val;
Sum[id]+=(ll)val*d;
}
}
ll query(int u)
{
ll res=0;
FOR(i,1,lv[u])
{
int id=Sid[u][i];ll d=dis[u][i];bool s=sgn[u][i];
if(s)res+=Sum[id]+d*sum[id];
else res-=Sum[id]+d*sum[id];
}
return res;
}
ll Query(int u)
{
ll res=query(u);
EOR(i,H,u)
{
int v=H.to[i],w=H.cost[i];
if(query(w)<=res)return Query(v);
}
return res;
} int main()
{
scanf("%d%d",&n,&q);
FOR(i,1,n-1)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
G.add(u,v,w),G.add(v,u,w);
}
int C,Mi=1e9;
CFS(1,0,n,C,Mi);
memset(mark,0,sizeof(mark));
memset(lv,0,sizeof(lv));
Sc=0;
dac(1,0,n);
while(q--)
{
int u,val;
scanf("%d%d",&u,&val);
update(u,val);
printf("%lld\n",Query(C));
}
return 0;
}

ZJOI 2015 幻想乡战略游戏(动态点分治)的更多相关文章

  1. [ZJOI2015]幻想乡战略游戏——动态点分治

    [ZJOI2015]幻想乡战略游戏 带修改下,边点都带权的重心 随着变动的过程中,一些子树内的点经过会经过一些公共边.考虑能不能对这样的子树一起统计. 把树上贡献分块. 考虑点分治算法 不妨先把题目简 ...

  2. 【BZOJ3924】[Zjoi2015]幻想乡战略游戏 动态树分治

    [BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网 ...

  3. 解题:ZJOI 2015 幻想乡战略游戏

    题面 神**所有点都爆int,我还以为我写出什么大锅了,不开long long见祖宗... 动态点分治利用点分树树高不超过log的性质,我们对每个点维护一个子树和,一个点分树子树和,一个点分树上父亲的 ...

  4. [BZOJ3924][ZJOI2015]幻想乡战略游戏(动态点分治)

    题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打 ...

  5. P3345 [ZJOI2015]幻想乡战略游戏 动态点分治

    \(\color{#0066ff}{ 题目描述 }\) 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越 ...

  6. 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治

    题目描述 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打 ...

  7. ZJOI2015 幻想乡战略游戏 动态点分治_树链剖分_未调完

    Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来, ...

  8. BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)

    这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= = 不得不说CLJ说得真的太简单了,实现方面根本没提. 首先我们可以先用树分治构建出这 ...

  9. [ZJOI2015][bzoj3924] 幻想乡战略游戏 [动态点分治]

    唉:-(动态点分治的思想真是复杂...... 先码住,再做几道题再来填坑 PS:接下来的Code因为用了倍增lca所以TLE一部分,但是懒得改成RMQ了...... Code: #include< ...

  10. loj 2135 「ZJOI2015」幻想乡战略游戏 - 动态点分治

    题目传送门 传送门 题目大意 给定一棵树,初始点权都为0,要求支持: 修改点权 询问带权重心 询问带权重心就在点分树上跑一下就行了.(枚举跳哪个子树更优) 剩下都是基础点分治. 学了一下11-dime ...

随机推荐

  1. Java多线程-----Thread常用方法

    1.public Thread(Runnable target,String name) 创建一个有名称的线程对象 package com.thread.mothed; public class Th ...

  2. Memento Mori (二维前缀和 + 枚举剪枝)

    枚举指的是枚举矩阵的上下界,然后根据p0, p1, p2的关系去找出另外的中间2个点.然后需要记忆化一些地方防止重复减少时间复杂度.这应该是最关键的一步优化时间,指的就是代码中to数组.然后就是子矩阵 ...

  3. Swift之关键字使用(I)

    static和class的使用 static 使用 在非class的类型(包括enum和struct)中,一般使用static来描述类型作用域.在这个类型中,我们可以在类型范围中声明并使用存储属性,计 ...

  4. STL容器之list

    [1]list简介 实质上,list容器就是一个双向链表,可以高效地进行插入.删除操作. [2]list链表常用方法 (1)构造.赋值.清空.删除.插入.判空等 应用示例代码如下: #include ...

  5. python-数据分析与展示(Numpy、matplotlib、pandas)---2

    笔记内容整理自mooc上北京理工大学嵩天老师python系列课程数据分析与展示,本人小白一枚,如有不对,多加指正 1.python自带的图像库PIL 1.1常用API  Image.open()    ...

  6. maven项目启动报错;class path resource [com/ssm/mapping/] cannot be resolved to URL because it does not exist

    项目启动报了一堆错误,其实都是class path resource [com/ssm/mapping/] cannot be resolved to URL because it does not ...

  7. jQuery获取子元素个数的方法

    //获取id=div1下的子元素的个数 $('#id').children().length; //获取id=div1下的p元素个数 $('#id').children('p').length;

  8. right spindle supply short to gnd

    hardware guy found that the R1004 lead to this error, but this error should not be checked, because ...

  9. Failed to load ApplicationContext

    java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.conte ...

  10. 标准库 svc—程序及服务控制

    对于程序及服务的控制,本质上而言就是正确的启动,并可控的停止或退出.在go语言中,其实就是程序安全退出.服务控制两个方面.核心在于系统信号获取.Go Concurrency Patterns.以及基本 ...