树链剖分

线段树维护区间最小值,区间最大值

更新,对于每一个区间,找到当前区间的最小值的最大值,和要更新的值比较,如果比最大值还大,则此数对于以后的询问无任何贡献,直接返回即可,若有贡献,则一直递归到叶子节点,将最值全部更新

询问,直接询问区间最小值即可

/*
Alice 和 Bob 在玩一个游戏。
游戏在一棵有 n 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 123456789123456789。
有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 r,若 r 与 s 的距离是 dis,那么 Alice 在点 r 上添加的数字是 a×dis+b。
有时,Bob 会选择一条从 s 到 t 的路径。他需要先从这条路径上选择一个点,再从那个点上选择一个数字。
Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 123456789123456789
#define maxn 100010
using namespace std;
inline int read(){
int s=,f=;char ch=getchar();
for(;ch<''||ch>'';ch=getchar())if(ch=='-')f=-;
for(;ch>=''&&ch<='';ch=getchar())s=s*+ch-'';
return s*f;
}
int n,m;
int fa[maxn][],dep[maxn],f[maxn];
struct edge{
int to,next,w;
}G[maxn<<];
int tot,h[maxn];
void add(int x,int y,int z){
tot++;G[tot].to=y;G[tot].next=h[x];G[tot].w=z;h[x]=tot;
}
int pos[maxn],sz,size[maxn],poz[maxn];
ll t[maxn<<],dis[maxn],mx[maxn<<];
void dfs(int x){
for(int i=;i<=;++i)
if(dep[x]<(<<i))break;
else fa[x][i]=fa[fa[x][i-]][i-];
for(int i=h[x];i;i=G[i].next){
int v=G[i].to;
if(dep[v])continue;
dep[v]=dep[x]+;
fa[v][]=x;
dis[v]=dis[x]+G[i].w;
dfs(v);
size[x]+=size[v];
}size[x]++;
}
void dfs(int x,int ff){
pos[x]=++sz;f[x]=ff;poz[sz]=x;
int mx=;
for(int i=h[x];i;i=G[i].next)
if(dep[G[i].to]>dep[x]&&size[G[i].to]>size[mx])
mx=G[i].to;
if(!mx)return;
dfs(mx,ff);
for(int i=h[x];i;i=G[i].next)
if(dep[G[i].to]>dep[x]&&mx!=G[i].to)
dfs(G[i].to,G[i].to);
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
int d=dep[x]-dep[y];
for(int i=;i<=;++i)
if(d&(<<i))
x=fa[x][i];
if(x==y)return x;
for(int i=;i>=;--i)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
if(x==y)return x;
return fa[x][];
}
void build(int k,int l,int r){
if(l==r){t[k]=inf;mx[k]=inf;return;}
int mid=(l+r)>>;
build(k<<,l,mid);build(k<<|,mid+,r);
t[k]=min(t[k<<],t[k<<|]);
mx[k]=max(mx[k<<],mx[k<<|]);
}
void init(){
n=read();m=read();
for(int i=;i<n;++i){
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}
dep[]=;dfs();
dfs(,);
build(,,n);
}
void work1(int k,int l,int r,int x,int y,ll a,ll b,ll d1,ll d2){
if(mx[k]<=a*d1+b&&mx[k]<=a*d2+b)return;
if(l==r){t[k]=a*d1+b,mx[k]=a*d1+b;return;}
int mid=(l+r)>>;
if(y<=mid)work1(k<<,l,mid,x,y,a,b,d1,d2);
else if(x>mid)work1(k<<|,mid+,r,x,y,a,b,d1,d2);
else work1(k<<,l,mid,x,mid,a,b,d1+dis[poz[y]]-dis[poz[mid]],d2),
work1(k<<|,mid+,r,mid+,y,a,b,d1,d1+dis[poz[y]]-dis[poz[mid+]]);
t[k]=min(t[k<<],t[k<<|]);
mx[k]=max(mx[k<<],mx[k<<|]);
}
void work2(int k,int l,int r,int x,int y,ll a,ll b,ll d1,ll d2){
if(mx[k]<=a*d1+b&&mx[k]<=a*d2+b)return;
if(l==r){t[k]=a*d1+b,mx[k]=a*d1+b;return;}
int mid=(l+r)>>;
if(y<=mid)work2(k<<,l,mid,x,y,a,b,d1,d2);
else if(x>mid)work2(k<<|,mid+,r,x,y,a,b,d1,d2);
else work2(k<<,l,mid,x,mid,a,b,d1,d1+dis[poz[mid]]-dis[poz[x]]),
work2(k<<|,mid+,r,mid+,y,a,b,d1+dis[poz[mid+]]-dis[poz[x]],d2);
t[k]=min(t[k<<],t[k<<|]);
mx[k]=max(mx[k<<],mx[k<<|]);
}
void work(int x,int y,ll a,ll b){
int k=lca(x,y);
int u=x;
while(f[x]!=f[k]){
work1(,,n,pos[f[x]],pos[x],a,b,dis[u]-dis[x],dis[u]-dis[f[x]]);x=fa[f[x]][];
}work1(,,n,pos[k],pos[x],a,b,dis[u]-dis[x],dis[u]-dis[k]);
while(f[y]!=f[k]){
work2(,,n,pos[f[y]],pos[y],a,b,dis[u]+dis[f[y]]-*dis[k],dis[u]+dis[y]-*dis[k]);y=fa[f[y]][];
}work2(,,n,pos[k],pos[y],a,b,dis[u]-dis[k],dis[u]+dis[y]-*dis[k]);
}
ll ask(int k,int l,int r,int x,int y){
if(x<=l&&r<=y)return t[k];
int mid=(l+r)>>;
if(y<=mid)return ask(k<<,l,mid,x,y);
if(x>mid)return ask(k<<|,mid+,r,x,y);
return min(ask(k<<,l,mid,x,y),ask(k<<|,mid+,r,x,y));
}
void work(int x,int y){
int k=lca(x,y);
ll ans=inf;
while(f[x]!=f[k]){
ans=min(ans,ask(,,n,pos[f[x]],pos[x]));x=fa[f[x]][];
}ans=min(ans,ask(,,n,pos[k],pos[x]));
while(f[y]!=f[k]){
ans=min(ans,ask(,,n,pos[f[y]],pos[y]));y=fa[f[y]][];
}ans=min(ans,ask(,,n,pos[k],pos[y]));
printf("%lld\n",ans);
}
void work(){
for(int i=;i<=m;++i){
int opt=read();
if(opt==){
int s=read(),t=read(),a=read(),b=read();
work(s,t,a,b);
}else{
int s=read(),t=read();
work(s,t);
}
}
}
int main(){
init();
work();
return ;
}

SDOI 2016 游戏的更多相关文章

  1. 数据结构(树链剖分,线段树):SDOI 2016 游戏

    4515: [Sdoi2016]游戏 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 351  Solved: 157[Submit][Status][ ...

  2. 【BZOJ 4600】【SDOI 2016】硬币游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=4600 转化成nim游戏 因为对于每一个反面朝上的硬币编号可以拆成\(2^a3^bc\),选择这个硬币 ...

  3. 【BZOJ 4515】【SDOI 2016 Round1 Day1 T3】游戏

    考场上写了lct,可惜当时对标记永久化的理解并不是十分深刻,导致调一个错误的程序调了4h+,最后这道题爆0了QwQ 现在写了树链剖分,用标记永久化的线段树维护轻重链,对于$s\rightarrow l ...

  4. SDOI 2016 Round1 Day1

    储能表 /* 引自zyz大佬的数学思想 */ #include<cstdio> #include<iostream> using namespace std; typedef ...

  5. SDOI 2016 数字配对

    题目大意:给定n个数字以及每个数字的个数和权值,将满足条件的数字配对,使得总代价不小于0,且配对最多 最大费用最大流拆点,对于每个点,连一条由S到该点的边,容量为b,花费为0,再连一条到T的边 对于每 ...

  6. SDOI 2016 征途 决策单调性

    题目大意:有一个数列,将其分成m段,求最小方差 先弄出n^3的dp,打出决策点,然后发现决策点是单调递增的,决策单调性搞一搞就可以了 #include<bits/stdc++.h> #de ...

  7. SDOI 2016 生成魔咒

    题目大意:一个字符串,刚开始为空,依次在后面添加一个字符,问每次添加完字符后本质不同的字符串有多少种 后缀自动机裸题,添加字符时,更新的结点个数即为新增加的子串 #include<bits/st ...

  8. SDOI 2016 排列计数

    题目大意:一个数列A,n个元素,其中m个元素不动,其他元素均不在相应位置,问有多少种排列 保证m个元素不动,组合数学直接计算,剩余元素错位排列一下即可 #include<bits/stdc++. ...

  9. 【BZOJ 4516】【SDOI 2016】生成魔咒

    http://www.lydsy.com/JudgeOnline/problem.php?id=4516 后缀自动机直接做...省选时cena评测竟然没有卡掉map 每次加一个字符,增加的子串数目为n ...

随机推荐

  1. iOS 版本号大小比较

    NSString *num1 = @"5.2.0";    NSString *num2 = @"5.3.0"; if ([num1 compare:num2 ...

  2. 第三十二篇:在SOUI2.0中像android一样使用资源

    SOUI2.0之前,在SOUI中使用资源通常是直接使用这个资源的name(一个字符串)来引用.使用字符串的好处在于字符串能够表达这个资源的意义,因此使用字符串也是现代UI引擎常用的方式. 尽管直接使用 ...

  3. maven权威指南学习笔记(五)—— POM

    1. 简介 Archetype插件通过 pom.xml 文件创建了一个项目.这就是项目对象模型 (POM),一个项目的声明性描述. 当Maven运行一个目标的时候,每个目标都会访问定 义在项目POM里 ...

  4. Spring 自带的定时任务

    需要几天后,或者某个时间后,定时查询数据.需要用到Spring自带的一个注解 @Scheduled(cron="0/5 * * * * ? ")//每隔5秒钟执行 创建一个clas ...

  5. 关于linux服务器上搭建ftp服务的流程

    小龙最近折腾了一个阿里云的服务器,买完了就要开始做那么多那么多的功课,小龙对ssh也是一知半解的状态,做个小笔记,发布下整个ftp服务的搭建过程,大神勿喷:) 一.aliyun Linux(Redha ...

  6. hoj 2662 经典状压dp // MyFirst 状压dp

    题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2662 1.引言:用dp解决一个问题的时候很重要的一环就是状态的表示,一般来说,一个数组即可保存状态. ...

  7. python学习6 web开发

    wsgi自带,用语构建简单服务器 例子 from wsgiref.simple_server import make_server def index(env, res): res('200 ok', ...

  8. d-规则

    [问题描述]对任意给定的m(m∈N+)和n(n∈N+),满足m<n,构造一初始集合:P={x|m≤x≤n,x∈N+} (m,n≤100).现定义一种d规则如下:若存在a∈P,且存在K∈N+ ,K ...

  9. 疑难问题解决备忘录(2)——ubuntu12.04分配swap

    分配swapdd if=/dev/zero of=Swap.disk bs=1M count=6k (count=1k创建1G的Swap,如果要创建6G则count=6k:这步比较慢) 创建swap文 ...

  10. 前端性能优化--为什么DOM操作慢?

    作为一个前端,不能不考虑性能问题.对于大多数前端来说,性能优化的方法可能包括以下这些: 减少HTTP请求(合并css.js,雪碧图/base64图片) 压缩(css.js.图片皆可压缩) 样式表放头部 ...