【描述】

给你一个图,一共有 N 个点,2*N-2 条有向边。

边目录按两部分给出

1、 开始的 n-1 条边描述了一颗以 1 号点为根的生成树,即每个点都可以由 1 号点

到达。

2、 接下来的 N-1 条边,一定是从 i 到 1(2<=i<=N)的有向边,保证每个点都能到

1

有 q 次询问:

1 x w :表示将第 x 条边的边权修改为 w

2 u v :询问 u 到 v 的最短距离

【输入格式】

第一行是 2 个整数 N,Q,表示一共 N 个点 Q 次询问

接下来是 N-1 行,每行 3 个整数 U,V,W,表示了前 N-1 条边,u 到 v 的有向边

接下来 N-1 行,每行 3 个整数 U,V,W,描述了每个点到 1 号点的边,V==1

接下来是 Q 行,表示 Q 次修改与询问

【输出格式】

若干行,每行回答一次询问

【输入样例】

5 9

1 3 1

3 2 2

1 4 3

3 5 4

5 1 5

3 1 6

2 1 7

4 1 8

2 1 1

2 1 3

2 3 5

2 5 2

1 1 100

2 1 3

1 8 30

2 4 2

2 2 4

【输出样例】

0

1

4

8

100

132

10

【数据规模】

20%数据 没有修改

30%数据 2<=N,Q<=1000 (其中有 10%数据没有修改)

100%数据 2<=N,Q<=100 000, 1 <=边权 <= 1000,000


今天考试唯一开了数组的题。

貌似就是讨论一下u和v的关系,

如果u是v的祖先直接求链的值,不然的话查询以u为根的子树中回到根的最优值就行了。

要维护这个信息,就dfs序/树剖把树给映射到序列上,维护dis[i]+w[i]的最优值,其中dis[i]表示i到根的距离,w[i]表示i回到根的距离。

修改第一类边显然是子树修改。

第二类边是单点修改。

还是挺简单的。

代码:

#include<bits/stdc++.h>
#define N 100005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define ll long long
using namespace std;
inline ll read(){
    ll ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
inline void write(ll x){
    if(x>9)write(x/10);
    putchar((x%10)^48);
}
int n,q,first[N],cnt=0,tot=0,top[N],fa[N],dep[N],num[N],pred[N],siz[N],hson[N],rec[N];
ll a[N],d[N];
struct edge{int v,next;ll w;}e[N<<2];
struct Node{int l,r;ll mn,add;}T[N<<2];
inline void add(int u,int v,ll w){e[++cnt].v=v,e[cnt].w=w,e[cnt].next=first[u],first[u]=cnt;}
inline void dfs1(int p){
    siz[p]=1;
    for(int i=first[p];i;i=e[i].next){
        int v=e[i].v;
        a[v]=a[p]+e[i].w,dep[v]=dep[p]+1,fa[v]=p,dfs1(v),siz[p]+=siz[v];
        if(siz[v]>siz[hson[p]])hson[p]=v;
    }
}
inline void dfs2(int p,int tp){
    top[p]=tp,num[p]=++tot,pred[tot]=p;
    if(!hson[p])return;
    dfs2(hson[p],tp);
    for(int i=first[p];i;i=e[i].next){
        int v=e[i].v;
        if(v!=hson[p])dfs2(v,v);
    }
}
inline ll min(ll a,ll b){return a<b?a:b;}
inline void pushup(int p){T[p].mn=min(T[lc].mn,T[rc].mn);}
inline void pushnow(int p,int v){T[p].add+=v,T[p].mn+=v;}
inline void pushdown(int p){if(T[p].add)pushnow(lc,T[p].add),pushnow(rc,T[p].add),T[p].add=0;}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r,T[p].add=0;
    if(l==r){T[p].mn=a[pred[l]]+d[pred[l]];return;}
    build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,ll v){
    if(ql>T[p].r||qr<T[p].l)return;
    if(ql<=T[p].l&&T[p].r<=qr)return pushnow(p,v);
    pushdown(p);
    if(qr<=mid)update(lc,ql,qr,v);
    else if(ql>mid)update(rc,ql,qr,v);
    else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
    pushup(p);
}
inline ll query(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return 1e18;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].mn;
    pushdown(p);
    if(qr<=mid)return query(lc,ql,qr);
    if(ql>mid)return query(rc,ql,qr);
    return min(query(lc,ql,mid),query(rc,mid+1,qr));
}
inline void swap(int&x,int&y){x^=y,y^=x,x^=y;}
inline int lca(int x,int y){
    while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);x=fa[top[x]];}
    return dep[x]<dep[y]?x:y;
}
int main(){
    freopen("graph.in","r",stdin);
    freopen("graph.out","w",stdout);
    n=read(),q=read();
    for(int i=1;i<n;++i){int u=read(),v=read();ll w=read();add(u,v,w);}
    for(int i=1;i<n;++i){int u=read(),v=read();ll w=read();rec[i]=u,d[u]=w;}
    dfs1(1),dfs2(1,1),build(1,1,n);
    while(q--){
        int op=read();ll x=read(),y=read();
        if(op==1){
            if(x<=n-1)update(1,num[e[x].v],num[e[x].v]+siz[e[x].v]-1,y-e[x].w),e[x].w=y;
            else update(1,num[rec[x-n+1]],num[rec[x-n+1]],y-d[rec[x-n+1]]),d[rec[x-n+1]]=y;
        }
        else{
            if(x==y){printf("0\n");continue;}
            if(lca(x,y)==x)write(query(1,num[y],num[y])-d[y]-query(1,num[x],num[x])+d[x]);
            else write(query(1,num[y],num[y])+query(1,num[x],num[x]+siz[x]-1)-query(1,num[x],num[x])+d[x]-d[y]);
            puts("");
        }
    }
    return 0;
}

2018.08.30 NOIP模拟 graph(dfs序/树剖+线段树)的更多相关文章

  1. 2018.08.30 NOIP模拟 kfib(矩阵快速幂+exgcd)

    [输入] 一行两个整数 n P [输出] 从小到大输出可能的 k,若不存在,输出 None [样例输入 1] 5 5 [样例输出] 2 [样例解释] f[0] = 2 f[1] = 2 f[2] = ...

  2. 2018.08.30 NOIP模拟 wall(模拟)

    [问题描述] 万里长城是中国强大的标志,长城在古代的用途主要用于快速传递军事消息和抵御 外敌,在长城上的烽火台即可以作为藏兵的堡垒有可以来点燃狼烟传递消息. 现在有一段 万里长城,一共有 N 个烽火台 ...

  3. BZOJ4999:This Problem Is Too Simple!(DFS序&树上差分&线段树动态开点:区间修改单点查询)

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x&l ...

  4. Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)

    题意: 给出一个具有N个点的树,现在给出两种操作: 1.get x,表示询问以x作为根的子树中,1的个数. 2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0). 思路:dfs序加上一个线 ...

  5. 【bzoj4771】七彩树 树链的并+STL-set+DFS序+可持久化线段树

    题目描述 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义 ...

  6. hdu5692【dfs序】【线段树】

    Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  7. 2018.08.22 NOIP模拟 or(线段树)

    or [描述] 构造一个长度为 n 的非负整数序列 x,满足 m 个条件,第 i 个条件为x[li] | x[li+1] | - | x[ri]=pi. [输入] 第一行两个整数 n,m.接下来 m ...

  8. 【62测试】【状压dp】【dfs序】【线段树】

    第一题: 给出一个长度不超过100只包含'B'和'R'的字符串,将其无限重复下去. 比如,BBRB则会形成 BBRBBBRBBBRB 现在给出一个区间[l,r]询问该区间内有多少个字符'B'(区间下标 ...

  9. 【DFS序】【线段树】bzoj4034 [HAOI2015]T2

    分开维护树的入栈序和出栈序,用两棵线段树.回答时就是用一颗的减去另一棵的. #include<cstdio> #include<algorithm> using namespa ...

随机推荐

  1. 机器学习入门-随机森林温度预测-增加样本数据 1.sns.pairplot(画出两个关系的散点图) 2.MAE(平均绝对误差) 3.MAPE(准确率指标)

    在上一个博客中,我们构建了随机森林温度预测的基础模型,并且研究了特征重要性. 在这个博客中,我们将从两方面来研究数据对预测结果的影响 第一方面:特征不变,只增加样本的数据 第二方面:增加特征数,增加样 ...

  2. 基于OpenGL编写一个简易的2D渲染框架-09 重构渲染器-Shader

    Shader 只是进行一些简单的封装,主要功能: 1.编译着色程序 2.绑定 Uniform 数据 3.根据着色程序的顶点属性传递顶点数据到 GPU 着色程序的编译 GLuint Shader::cr ...

  3. 脚本中 %~dp0

    cmd窗口中 for /? 查询参数含义 %~dp0, 将参数转换为磁盘路径+名字 例: 脚本中一行 %~dp0abc.exe (abc.exe位置c:\test\abc.exe) 展开后则为 c:\ ...

  4. unity 查找脚本被场景中哪些对象引用

    在需要查找的脚本上右键: 在场景中已经显示出所有引用该脚本的对象

  5. Social media users of the world unite!

    Social media users of the world unite!全世界社交媒体用户联合起来!If Plato were alive today, he might well regard ...

  6. Quartz+TopShelf实现Windows服务作业调度

    Quartz:首先我贴出来了两段代码(下方),可以看出,首先会根据配置文件(quartz.config),包装出一个Quartz.Core.QuartzScheduler instance,这是一个调 ...

  7. hibernate中.常见的hql查询语句

    hql是非常有意识的被设计为完全面向对象的查询 基本规则: 1.hql语法类似于sql,但它后面跟的不是表名和字段名,而是类名和属性名 2.hql大小写不敏感.但是设计java类名,包名,属性名时大小 ...

  8. eclispe 通过git向码云上传

    本文将介绍如何将本地的项目提交到开源中国上去,过程比较详细,实现起来很简单.由于自己也算是一个新手,所以没有做过多的解释,只是单纯的描述了该如何去做. 1.在开源中国上面新建一个空项目 到这里也就结束 ...

  9. ORACLE 对一个表进行循环查数,再根据MO供给数量写入另一个新表

    一. 加工处理后要变成如下效果 create table test1 (sonum varchar2(10),lineid varchar2(10),qty int ,qty2 int ,remark ...

  10. Sum of Consecutive Prime Numbers

    Sum of Consecutive Prime Numbers http://poj.org/problem?id=2739 Time Limit: 1000MS   Memory Limit: 6 ...