假设是序列问题,且$S<T$,可以贪心求解,通过维护下述信息进行区间合并。

对于区间$[l,r]$,维护的信息有:

$v$:跳到了$\geq r$的位置后,可以花费$1$往右最多扩展多少。

$f[i]$:从$\leq l+i$开始跳到$\geq r$的位置的最少步数。

$g[i]$:从$\leq l+i$开始跳到$\geq r$的位置时,在$f$最小的基础上,可以花费$0$往右最多扩展多少。

然后树链剖分+线段树维护信息即可。

时间复杂度$O(am\log^2n)$。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100005,M=262150,K=20;
int n,m,i,x,y,a[N],g[N],v[N<<1],nxt[N<<1],ed,f[N],d[N],size[N],son[N],top[N],loc[N],q[N],dfn;char op;
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void merge(int&f,int&g,int x,int y){if(x<f||x==f&&y>g)f=x,g=y;}
struct P{
int f[K],g[K],v,len;
P(){}
P operator+(const P&b){
P c;
for(int i=0;i<K;i++){
if(i<len){
if(g[i]>=b.len){
c.f[i]=f[i];
c.g[i]=g[i]-b.len;
}else if(g[i]){
c.f[i]=f[i]+b.f[g[i]-1];
c.g[i]=b.g[g[i]-1];
}else c.f[i]=N;
if(v>=b.len)merge(c.f[i],c.g[i],f[i]+1,v-b.len);
else merge(c.f[i],c.g[i],f[i]+b.f[v-1]+1,b.g[v-1]);
}else{
if(i-len>=b.len)break;
c.f[i]=b.f[i-len];
c.g[i]=b.g[i-len];
}
}
c.v=max(v-b.len,b.v);
c.len=len+b.len;
for(int i=1;i<K;i++)if(c.f[i]>c.f[i-1]||c.f[i]==c.f[i-1]&&c.g[i]<c.g[i-1])c.f[i]=c.f[i-1],c.g[i]=c.g[i-1];
for(int i=c.len;i<K;i++)c.f[i]=N,c.g[i]=0;
return c;
}
void set(int x){
v=x,len=1;
f[0]=g[0]=0;
for(int i=1;i<K;i++)f[i]=N,g[i]=0;
}
}vl[M],vr[M],tmp;bool flag;
inline void up(int x){
vl[x]=vl[x<<1]+vl[x<<1|1];
vr[x]=vr[x<<1|1]+vr[x<<1];
}
void build(int x,int a,int b){
if(a==b){
vl[x].set(q[a]);
vr[x].set(q[a]);
return;
}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
}
void change(int x,int a,int b,int c,int d){
if(a==b){
vl[x].set(d);
vr[x].set(d);
return;
}
int mid=(a+b)>>1;
if(c<=mid)change(x<<1,a,mid,c,d);
else change(x<<1|1,mid+1,b,c,d);
up(x);
}
void askl(int x,int a,int b,int c,int d){
if(c<=a&&b<=d){
if(flag)tmp=tmp+vl[x];else tmp=vl[x],flag=1;
return;
}
int mid=(a+b)>>1;
if(c<=mid)askl(x<<1,a,mid,c,d);
if(d>mid)askl(x<<1|1,mid+1,b,c,d);
}
void askr(int x,int a,int b,int c,int d){
if(c<=a&&b<=d){
if(flag)tmp=tmp+vr[x];else tmp=vr[x],flag=1;
return;
}
int mid=(a+b)>>1;
if(d>mid)askr(x<<1|1,mid+1,b,c,d);
if(c<=mid)askr(x<<1,a,mid,c,d);
}
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x){
size[x]=1;d[x]=d[f[x]]+1;
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
f[v[i]]=x,dfs(v[i]);
size[x]+=size[v[i]];
if(size[v[i]]>size[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int y){
q[loc[x]=++dfn]=a[x];top[x]=y;
if(son[x])dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]&&v[i]!=son[x])dfs2(v[i],v[i]);
}
inline int lca(int x,int y){
for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y);
return d[x]<d[y]?x:y;
}
int cnt,pool[1000][2];
inline int query(int x,int y){
int z=lca(x,y);
flag=cnt=0;
while(top[x]!=top[z]){
askr(1,1,n,loc[top[x]],loc[x]);
x=f[top[x]];
}
askr(1,1,n,loc[z],loc[x]);
while(top[y]!=top[z]){
pool[++cnt][0]=loc[top[y]];
pool[cnt][1]=loc[y];
y=f[top[y]];
}
if(y!=z){
pool[++cnt][0]=loc[z]+1;
pool[cnt][1]=loc[y];
}
for(int i=cnt;i;i--)askl(1,1,n,pool[i][0],pool[i][1]);
return tmp.f[0];
}
int main(){
read(n);
for(i=1;i<=n;i++)read(a[i]);
for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
dfs(1);
dfs2(1,1);
build(1,1,n);
read(m);
while(m--){
while((op=getchar())!='Q'&&op!='C');
read(x),read(y);
if(op=='C')change(1,1,n,loc[x],y);
else printf("%d\n",query(x,y));
}
return 0;
}

  

BZOJ3644 : 陶陶的旅行计划的更多相关文章

  1. COGS 2. 旅行计划

    2. 旅行计划 ★☆   输入文件:djs.in   输出文件:djs.out   简单对比时间限制:3 s   内存限制:128 MB 过暑假了,阿杜准备出行旅游,他已经查到了某些城市的两两之间的距 ...

  2. P1676陶陶吃苹果 - vijos

    描述 curimit知道陶陶很喜欢吃苹果.于是curimit准备在陶陶生日的时候送给他一棵苹果树. curimit准备了一棵这样的苹果树作为生日礼物:这棵苹果树有n个节点,每个节点上有c[i]个苹果, ...

  3. Crash的旅行计划

    除草了.. Crash的旅行计划 [问题描述] 过不了多久,Crash就要迎来他朝思暮想的暑假.在这个暑假里,他计划着到火星上旅游.在火星上有N个旅游景点,Crash用1至N这N个正整数对这些景点标号 ...

  4. bzoj 2402: 陶陶的难题II 二分答案维护凸包

    2402: 陶陶的难题II Time Limit: 40 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 68  Solved: 45[Submi ...

  5. bzoj 2401: 陶陶的难题I 数论

    2401: 陶陶的难题I Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 89  Solved: 24[Submit][Status] Descript ...

  6. 武汉科技大学ACM:1007: 陶陶摘苹果

    Problem Description 厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试. 个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高度,请帮陶陶算一下她能够摘到的苹 ...

  7. 洛谷-陶陶摘苹果(升级版)-BOSS战-入门综合练习1

    题目描述 Description 又是一年秋季时,陶陶家的苹果树结了n个果子.陶陶又跑去摘苹果,这次她有一个a公分的椅子.当他手够不着时,他会站到椅子上再试试. 这次与NOIp2005普及组第一题不同 ...

  8. NOIP2005-普及组复赛-第一题-陶陶摘苹果

    题目描述 Description 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳 ...

  9. noip普及组2005 陶陶摘苹果

    陶陶摘苹果 描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试. 现在 ...

  10. 2719:陶陶摘苹果-poj

    2719:陶陶摘苹果 总时间限制:  1000ms 内存限制:  65536kB 描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米 ...

随机推荐

  1. Android相关 博客收藏

    #1 Android 网络编程 参考博客 :http://blog.csdn.net/kieven2008/article/details/8210737 #2 Could not find com. ...

  2. 开启Java之旅

    学习应用系统的服务器开发,也许并不算什么“旅行”,也不会那么‘愉快’.但是,我希望这次能够同以往有所不同,更加努力地学习J2EE. 从2月份开始,从事web前端开发,并在公司的的项目中,独立完成了4个 ...

  3. 没有-jackson相关依赖会抛出如下异常--------在spring官方文档有解释

    <!--jackson相关依赖--><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackso ...

  4. weixinShare.js / 极简微信分享插件

    weixinShare.js / 极简微信分享插件 / 版本:0.1 这是一个很简单.很实用的微信分享插件,无需jQuery,只需要在网页里加入一行JS代码,即可自动识别微信浏览器并启动微信分享的提示 ...

  5. 腾讯应用宝Android 应用加固(乐固)操作说明(转)

    此处引用腾讯云对加固的优点说明如下: 为什么应用需要加固? 若应用不做任何安全防护,极易被病毒植入.广告替换.支付渠道篡改.钓鱼.信息劫持等,严重侵害开发者的利益. 应用进行安全防护,防止应用分发后, ...

  6. [转] 前后端分手大师——MVVM 模式

    之前对 MVVM 模式一直只是模模糊糊的认识,正所谓没有实践就没有发言权,通过这两年对 Vue 框架的深入学习和项目实践,终于可以装B了有了拨开云雾见月明的感觉. Model–View–ViewMod ...

  7. bzoj3992

    题解: 求模素数 p 原根的方法:对 p-1 进行素因子分解,记pi为p-1的第i个因子,若恒有a^((p-1)/pi) mod p ≠ 1  成立,则 a 就是 p 的原根.(对于合数求原根,只需把 ...

  8. 关于LookUp的切换实例

    在关注了很久后发现还是有太多的东西没有记住,需要自己一步一步地去学习!不用太关注太多的杂乱的事,只用关注自己一点一滴,我相信所有的一切都会有一个很好的结局.

  9. 聊聊Docker数据卷和数据卷容器

    当程序在容器运行的时候,特别是需要与其他容器中的程序或容器外部程序进行沟通交流,这时需要进行数据交换,作为常用的两种沟通数据的方式,网络通信与文件读写是需要提供给程序的支持, [数据卷] 文件是数据持 ...

  10. Mybatis关联一对多映射不能查询出所有的数据的问题

    在使用Mybatis进行一对多查询时,如果返回的是一个对象的话,可以发现将一对多的数据全都取出来了,但是这样的缺点是有很多值为null,我们更喜欢将返回值设为Map的形式,这样可以去除那些多余null ...