3531: [Sdoi2014]旅行

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1197  Solved: 576
[Submit][Status][Discuss]

Description

S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足
从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教,  S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
    在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
    由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。    为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。

Input

输入的第一行包含整数N,Q依次表示城市数和事件数。
    接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的
评级和信仰。
    接下来N-1行每行两个整数x,y表示一条双向道路。
    接下来Q行,每行一个操作,格式如上所述。

Output

对每个QS和QM事件,输出一行,表示旅行者记下的数字。

Sample Input

5 6
3 1
2 3
1 2
3 3
5 1
1 2
1 3
3 4
3 5
QS 1 5
CC 3 1
QS 1 5
CW 3 3
QS 1 5
QM 2 4

Sample Output

8
9
11
3

HINT

N,Q < =10^5    , C < =10^5

数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时

刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。

Source

Round 1 Day 1

[Submit][Status][Discuss]



【因为每个城市的信仰不同,而旅人只能在与其起点信仰相同的城市留宿,即在查询时,只能将与起点信仰相同的城市的评级计算进和或最大值,所以显然,建一棵线段树不能满足要求,所以要按不同信仰,每种信仰建一棵线段树(参考主席树的方式),每棵线段树维护两个值:和与最大值。查询时直接在相同信仰的线段树中查询即可】

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int a[200010],next[200010],p[100010],tot;//next数组
int fa[100010],son[100010],size[100010],dep[100010];//fa是存每个节点的父节点,son存每个节点的重儿子,size存每个节点所控制的节点数(包含它自己),dep表示每个节点的深度
int trn1[100010],top[100010],tip;//trn1表示每个节点在线段树里的编号,top表示每个节点所在链的头结点
int tree1[40000010],tree2[40000010],L[4000010],R[4000010],root[100010],g;//tree1是维护和的线段树,tree2是维护最大值的线段树,L是存每棵线段树的左子树的根的标号,R是存每棵线段树的右子树的根的编号,root存每棵线段树的根的编号(即当前线段树是信仰编号为几的线段树)
int n,m,w[100010],v[100010];//w是每个城市的评级,v是每个城市的信仰
void add(int x,int y)
{tot++; a[tot]=y; next[tot]=p[x]; p[x]=tot;tot++; a[tot]=x; next[tot]=p[y]; p[y]=tot;
}void dfs1(int now,int father,int h)
{fa[now]=father; dep[now]=h; size[now]=1;int u=p[now];while (u!=0){int y=a[u];if (y!=father) {dfs1(y,now,h+1);size[now]+=size[y];if (son[now]==-1||size[y]>size[son[now]]) son[now]=y;}u=next[u];}
}
void dfs2(int now,int tp)
{top[now]=tp; trn1[now]=++tip;if (son[now]==-1) return;dfs2(son[now],tp);int u=p[now];while (u!=0){int y=a[u];if (y!=fa[now]&&y!=son[now])dfs2(y,y);u=next[u];}
}//树链剖分部分void updata(int rt)
{tree1[rt]=tree1[L[rt]]+tree1[R[rt]];tree2[rt]=max(tree2[L[rt]],tree2[R[rt]]);
}
void build(int &rt,int l,int r,int now,int val)
{if (!rt) rt=++g;//如果这是一种新的信仰,则新开一棵线段树 if (l==r){ tree1[rt]=val; tree2[rt]=val; return;}int mid=(l+r)>>1;if (now<=mid) build(L[rt],l,mid,now,val);else build(R[rt],mid+1,r,now,val);updata(rt);
}//建树和单点修改
int ask1(int rt,int al,int ar,int l,int r)
{if (!rt) return 0;if (al<=l&&ar>=r) return tree1[rt];int mid=(l+r)>>1,ans=0;if (al<=mid) ans+=ask1(L[rt],al,ar,l,mid);if (ar>mid) ans+=ask1(R[rt],al,ar,mid+1,r);return ans;
}//查询区间和
int ask2(int rt,int al,int ar,int l,int r)
{if (!rt) return 0;if (al<=l&&ar>=r) return tree2[rt];int mid=(l+r)>>1,ans=-0x7fffffff;if (al<=mid) ans=max(ans,ask2(L[rt],al,ar,l,mid));if (ar>mid) ans=max(ans,ask2(R[rt],al,ar,mid+1,r));return ans;
}//查询区间最大值
int a1(int x,int y,int rt)
{int ans=0;while (top[x]!=top[y]){if (dep[top[x]]<dep[top[y]]) swap(x,y);ans+=ask1(rt,trn1[top[x]],trn1[x],1,n);x=fa[top[x]];}if (dep[x]>dep[y]) swap(x,y);ans+=ask1(rt,trn1[x],trn1[y],1,n);return ans;
}//查询区间和的预处理(因为x,y可能不在一条链里,序号也不一定谁大谁小,所以要跑一个类似一个lca的东西,当他们不在一条链上时,先将较深的那段跑完,再跑在同一条链上的。 和原来区间修改时相似)
int a2(int x,int y,int rt)
{int ans=-0x7ffffffff;while (top[x]!=top[y]){if (dep[top[x]]<dep[top[y]]) swap(x,y);ans=max(ans,ask2(rt,trn1[top[x]],trn1[x],1,n));x=fa[top[x]];}if (dep[x]>dep[y]) swap(x,y);ans=max(ans,ask2(rt,trn1[x],trn1[y],1,n));return ans;
}//查询区间最大值的预处理 int main()
{int i;memset(son,-1,sizeof(son));scanf("%d%d",&n,&m);for (i=1;i<=n;++i) scanf("%d%d",&w[i],&v[i]);for (i=1;i<n;++i) {int x,y; scanf("%d%d",&x,&y); add(x,y);}dfs1(1,0,1); dfs2(1,1);for (i=1;i<=n;++i) build(root[v[i]],1,n,trn1[i],w[i]);//按不同信仰建多棵线段树,同一信仰的点放在同一棵线段树里 for (i=1;i<=m;++i){char c[10]; int x,y;scanf("%s%d%d",c,&x,&y);if (c[0]=='C')if (c[1]=='C'){build(root[v[x]],1,n,trn1[x],0); build(root[y],1,n,trn1[x],w[x]); v[x]=y; continue;}//将编号为x的城市的信仰改为y,即将原来线段树中城市x的评级改为0,再在信仰为y的线段树里加上城市x的评级,最后别忘将存x的信仰的v改为y,不然查询时会出错 else {build(root[v[x]],1,n,trn1[x],y); w[x]=y; continue;}//将编号为x的城市的评级改为y,直接更改即可,不过改完后,也要将w[x]更改成当前值 elseif (c[1]=='S')printf("%d\n",a1(x,y,root[v[x]]));//查询旅人从城市x到城市y记录的城市评级的和(只能记录与城市x信仰相同的),直接在以信仰v[x]为根的线段树里查询tree1即可 else printf("%d\n",a2(x,y,root[v[x]]));//查询旅人从城市x到城市y记录的城市评级最大值(只能记录与城市x信仰相同的),直接在以信仰v[x]为根的线段树里查询tree2即可 }return 0;
}

转载于:https://www.cnblogs.com/lris-searching/p/9403148.html

【bzoj 3531】 [Sdoi2014]旅行(树链剖分+树套树)相关推荐

  1. BZOJ 3531[Sdoi2014]旅行

    BZOJ 3531[Sdoi2014]旅行 题面描述 传送门 题目分析 可以考虑到,如果这个题所有城市都只信一种宗教的话,就是一个sb树剖,直接进行链的查询和修改就能搞定.多个宗教的话,可以有一种暴力 ...

  2. BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2157 是 hydro 的 BZOJ ...

  3. BZOJ 2402 陶陶的难题II (树链剖分、线段树、凸包、分数规划)

    毒瘤,毒瘤,毒瘤-- \(30000\)这个数据范围,看上去就是要搞事的啊... 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2402 ...

  4. BZOJ 3779 重组病毒 LCT,树链剖分,线段树

    题意: 给一棵树,每个点一开始颜色互不相同,支持三个操作                 1. 将一个点到根的路径染成一种新的颜色                 2. 将一个新的点设为根,并将原来的 ...

  5. [Bzoj4196] [NOI2015] 软件包管理器 [树链剖分,线段树]

    题解摘要:树链剖分后用线段树区间查询修改,对于安装软件,将改点到根的路径全部变为1,对于卸载软件,将子树清空.注意边界,编号是从0开始的,容易漏掉树根. 第一次写树剖- 1 #include < ...

  6. Luogu P5556 圣剑护符(线性基,树链剖分,线段树)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Problem 小L 和 小K 面前的圣剑由 nnn 块护符组成,分别编号为 1,2,-,n1,2,\ ...

  7. Tree HDU - 6547 (树链剖分,线段树)

    wls 有三棵树,树上每个节点都有一个值 ai,现在有 2 种操作: 将一条链上的所有节点的值开根号向下取整: 求一条链上值的和: 链的定义是两点之间的最短路. Input 第一行两个数 n, q 分 ...

  8. 兰州大学第一届 飞马杯 ★★快乐苹果树★★ 树链剖分 + 懒标记 + 树状数组

    传送门 文章目录 题意: 思路: 题意: 思路: 第一次听说树链剖分能在fa[top[i]]fa[top[i]]fa[top[i]]的地方加懒标记,学到了学到了. 首先不能被题目吓住,这个题目仔细剖析 ...

  9. 清明梦超能力者黄YY[树链剖分+扫描线,线段树合并]

    清明梦超能力者黄YY 题目连接 https://www.nowcoder.com/acm/contest/206/I 暂时有两种做法. 算法一 涉及:树链剖分,扫描线 在一个线段的情况下,我们可以把一 ...

  10. hdu5111 树链剖分,主席树

    hdu5111 链接 hdu 思路 先考虑序列上如何解决. 1 3 2 5 4 1 2 4 5 3 这个序列变成 1 2 3 4 5 1 3 5 5 2 是对答案没有影响的(显然). 然后查询操作\( ...

最新文章

  1. MySQL - 剖析MySQL索引底层数据结构
  2. Loj#3130-「COCI 2018.12」Praktični【线性基】
  3. lambdas 排序_Java8 Lambdas:解释性能缺陷的排序
  4. Android 系统(156)----Android APP适配全面屏手机的技术要点
  5. html语言标记滚动字幕,网页滚动文字的制作HTML代码
  6. 海思视频监控芯片如何一步步成为行业霸主
  7. 单机 弱联网手游 防破解 金币修改 简单措施
  8. Mac OS系统怎么修改mac地址
  9. Mac —— QuickTime录屏 声音小解决
  10. The scripts f2py, f2py3 and f2py3.8 are installed in ‘/home/cyd/.local/bin‘ which is not on PATH
  11. SF58-ASEMI快恢复二极管SF58的发展意义
  12. 电脑上怎样下载喜马拉雅里的 Mp3
  13. 校园综合服务平台-微信小程序
  14. 服务器是嵌入式系统吗,常见的几种嵌入式web服务器
  15. 笔记本电脑C盘满了清理方法大全
  16. 刷脸支付设备深度融合多项赋能
  17. linux 命令断网,linux 断网 扫描基本命令(示例代码)
  18. python取json数组中的值
  19. 459. Repeated Substring Pattern
  20. 概念---金融工程1:外汇的无套利定价模型

热门文章

  1. 计算一个连通分量中节点的个数的两种方法
  2. WPF自定义开关切换按钮
  3. MySQL怎么查同一列多行展示_一个MySQL查询将多个行中的字符串合并为一行,并在另一列中显示相应的用户ID总和?...
  4. 查看文件_如何在Mac上显示和查看隐藏的文件/文件夹
  5. 本地提交spark_spark快速入门(三)-------spark部署及运行模式
  6. python杨辉三角函数_Python算法之六:杨辉三角
  7. Python源码深度解析—对象的创建
  8. [leetcode]5321. 阈值距离内邻居最少的城市
  9. UnityShader3:ShaderLab
  10. 人群与网络:搜索引擎广告位的定价