[SDOI2014]旅行

[SDOI2014]旅行

题意:

n个城市,n-1条边,任意两个城市互通,每个城市有所信奉的宗教和城市评级,有四种指令:
1.将城市x的居民改信为c教
2.将城市x的评级调整为w
3.统计x到y,路上所有的城市的评级综合(被记录的城市宗教必须与x和y相同,数据保证x和y宗教一致)
4.统计x到y,路上的评级最大值(被记录的城市要求与上述一样)
按照要求输出答案

题解:

参考文章为洛谷题解的第一篇(文章好像显示不可查看
洛谷的题解第一页
题目比较麻烦,因为有两个要维护的量,如果是一个还好说,对于树上维护那肯定是树链剖分,现在关键就是如果确保只统计同一宗教的评级
我们可以将每个宗教建立一个线段树这样分开维护不久ok了,但是内存会超,那我们就主席树,动态开点
现在讲讲具体细节:
动态开点就不说了
我们讲讲改信其他教和评级调整如何实现?
原本是a教,改成c教
那我们就先到a教的线段树中找到这个点,然后将其评级和评级最大值都清零(可以理解为删除这个点,但实际还存在只是没有值),然后到c教里将这个点再加上,并加上评级
注意:在删除过程中记得要pushup(root),你删除一个点后,整个数的最大值和权值和发生了改变,所以即可更新到根节点
评级更新也是差不多,先把原本评级删去,再附上新评级
剩下都是树链剖分常规操作
代码有详细注释

代码:

#include<bits/stdc++.h>
using namespace std;
struct node{int to,next;
}g[1000000];
int tot,n,m,cnt,w[100004],zj[100004],len,head[100004],dep[100004],wson[100004],top[100004],tpos[100004],pre[100004],fa[100004],size[100004];
inline void made(int from,int to){g[++tot].to=to;g[tot].next=head[from];head[from]=tot;
}
inline void dfs1(int rt,int ff){fa[rt]=ff;dep[rt]=dep[ff]+1;size[rt]=1;for (int i=head[rt];i;i=g[i].next){int v=g[i].to;if (v==ff) continue;dfs1(v,rt);size[rt]+=size[v];if (!wson[rt]||size[wson[rt]]<size[v]) wson[rt]=v;}
}
inline void dfs2(int rt,int tops){tpos[rt]=++cnt;pre[cnt]=rt;top[rt]=tops;if (wson[rt]) dfs2(wson[rt],tops);for (int i=head[rt];i;i=g[i].next){int v=g[i].to;if (v==fa[rt]||v==wson[rt]) continue;dfs2(v,v);}
}
int root[100004];
struct Node{int l,r,max,tot;
}tree[20000110];
inline void update(int &rt,int w,int l,int r,int pos){//加点操作 if (!rt) rt=++len;//动态开点 tree[rt].max=max(tree[rt].max,w);tree[rt].tot+=w;if (l==r) return;int mid=(l+r)/2;if (mid>=pos) update(tree[rt].l,w,l,mid,pos);else update(tree[rt].r,w,mid+1,r,pos);
}
inline void remove(int &rt,int l,int r,int pos){//删点操作 if (l==r){ tree[rt].tot=0;tree[rt].max=0;return; }int mid=(l+r)/2;if (mid>=pos) remove(tree[rt].l,l,mid,pos);else remove(tree[rt].r,mid+1,r,pos);tree[rt].tot=tree[tree[rt].l].tot+tree[tree[rt].r].tot;tree[rt].max=max(tree[tree[rt].l].max,tree[tree[rt].r].max);
}inline int querytot(int rt,int lb,int rb,int l,int r){//查询区间总值 if (r<lb||l>rb) return 0;if (r>=rb&&l<=lb) return tree[rt].tot;int mid=(lb+rb)/2;return querytot(tree[rt].l,lb,mid,l,r)+querytot(tree[rt].r,mid+1,rb,l,r);
}
inline int querymax(int rt,int lb,int rb,int l,int r){//查询区间最大值 if (r<lb||l>rb) return 0;if (r>=rb&&l<=lb) return tree[rt].max;int mid=(lb+rb)/2;return max(querymax(tree[rt].l,lb,mid,l,r),querymax(tree[rt].r,mid+1,rb,l,r));
}
//--上面为动态开点线段树,下面为树链剖分 
inline int sigmax(int u,int v,int zj){int ans=0;while (top[u]!=top[v]){if (dep[top[u]]<dep[top[v]]) swap(u,v);ans=max(ans,querymax(root[zj],1,n,tpos[top[u]],tpos[u]));u=fa[top[u]];}if (dep[u]<dep[v]) swap(u,v);ans=max(ans,querymax(root[zj],1,n,tpos[v],tpos[u]));return ans;
}
inline int sigtot(int u,int v,int zj){int ans=0;while (top[u]!=top[v]){if (dep[top[u]]<dep[top[v]]) swap(u,v);ans=ans+querytot(root[zj],1,n,tpos[top[u]],tpos[u]);u=fa[top[u]];}if (dep[u]<dep[v]) swap(u,v);ans=ans+querytot(root[zj],1,n,tpos[v],tpos[u]);return ans;
}
char s[100];
int main(){len=0;scanf("%d%d",&n,&m);for (int i=1;i<=n;i++){scanf("%d%d",&w[i],&zj[i]);}int x,y;for (int i=1;i<n;i++){scanf("%d%d",&x,&y);made(x,y);made(y,x);}dfs1(1,0);dfs2(1,1);for (int i=1;i<=n;i++){update(root[zj[i]],w[i],1,n,tpos[i]);}		while (m--){scanf("%s",s);scanf("%d%d",&x,&y);switch (s[1]){case 'C':{//改信了c教 remove(root[zj[x]],1,n,tpos[x]);zj[x]=y;update(root[zj[x]],w[x],1,n,tpos[x]);break;}case 'W':{//城市x的评级调整为w;remove(root[zj[x]],1,n,tpos[x]);w[x]=y;update(root[zj[x]],w[x],1,n,tpos[x]);break;}case 'S':{//记录评级总和 printf("%d\n",sigtot(x,y,zj[x]));break;} case 'M':{//记录评级最大值 printf("%d\n",sigmax(x,y,zj[x]));break;}}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317580.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YbtOJ-染色计划【树链剖分,线段树,tarjan】

正题 题目大意 给出nnn个点的一棵树&#xff0c;每个点有个颜色aia_iai​&#xff0c;你每次可以选择一个颜色全部变成另一个颜色。 求最少多少次操作可以把一种颜色变成一个完整的连通块。 1≤k≤n≤21051\leq k\leq n\leq 2\times 10^51≤k≤n≤2105 解题思路 考虑如果我们…

张高兴的 .NET Core IoT 入门指南:环境配置、Blink、部署

如何在 Raspberry Pi 的 Raspbian 上构建使用 GPIO 引脚的 IoT 程序&#xff1f;你可能会回答使用 C 或 Python 去访问 Raspberry Pi 的引脚。现在&#xff0c;C# 程序员可以使用 .NET Core 在 Raspbian(Linux) 上构建 IoT 应用程序。只需要引入 System.Device.GPIONuGet 包即可…

CF183C:Diverse Permutation(构造)

解析 首先考虑如何构造kn-1的情况 发现令排列为1,n,2,n-1…即可 那么在k不等于n-1时 只需要让前k项与上面的序列相同&#xff0c;后面公差为1即可 代码 #include<bits/stdc.h> using namespace std; #define ll long long #define ull unsigned long long const int N…

CF603E-Pastoral Oddities【CDQ分治,可撤销并查集】

正题 题目链接:https://www.luogu.com.cn/problem/CF603E 题目大意 开始时有nnn个点&#xff0c;没有边。 依次加入mmm条带权的边&#xff0c;每次加入后询问是否存在一个边集&#xff0c;满足每个点的度数均为奇数&#xff0c;求使得这个边集的最大权值最小。 1≤n≤105,1≤…

2020ICPC 江西省大学生程序设计竞赛

2020ICPC 江西省大学生程序设计竞赛

在AspNetMvc中使用日志面板. Logdashboard 1.1beta

Logdashboard是Net下的日志面板,它支持AspNet与AspNetCore项目。关于更多LogDashboard的介绍请看这里--使用logdashboard查看可视化日志。就在刚刚LogDashboard发布了1.1的beta版,在这个版本中有以下变化https://github.com/liangshiw/LogDashboard/releases支持NetFramework的…

【正睿2021寒假省选第二轮集训 day 1】令牌生成 (组合数+二分)

description solution 打表yyds 其实符合条件的个数跟nnn&#xff08;非题目中的意思&#xff09;有着等差数列公式的千丝万缕关系 所以可以二分出具体值 最后答案的取值范围一定是长成[,)[,)[,)&#xff0c;左闭右开的形式的 而且两个边界一定是只差了最小的那个111&#xff…

CF600F:Edge coloring of bipartite graph(二分图、构造)

解析 首先大胆猜结论&#xff1a;答案就是最大的点度数 考虑如何构造 设一个点联通的边的颜色集合为S&#xff0c;由题意得S中的元素不可重 假设新加入一条边(u,v) 设c1mex(Su),c2mex(Sv)c1mex(S_u),c2mex(S_v)c1mex(Su​),c2mex(Sv​) 如果c1等于c2&#xff0c;直接连就行了…

CF464E-The Classic Problem【最短路,主席树】

正题 题目链接:https://www.luogu.com.cn/problem/CF464E 题目大意 nnn个点mmm条边的一张无向图&#xff0c;第iii条边长度为2xi2^{x_i}2xi​&#xff0c;求sss到ttt的最短路。 1≤n≤105,0≤m,xi≤1051\leq n\leq 10^5,0\leq m,x_i\leq 10^51≤n≤105,0≤m,xi​≤105 解题思路…

.NETStandard FreeSql v0.0.9 功能预览

年关将至&#xff0c;首页技术含量文章真是越来越少&#xff0c;理解大家盼着放假过年&#xff0c;哥们我何尝不是&#xff0c;先给大家拜个早年。兄弟我从11月底发了神经&#xff0c;开启了 ORM 功能库的开发之旅&#xff0c;历时两个月编码和文档整理&#xff0c;目前预览版本…

【CF868F】Yet Another Minimization Problem (决策单调性优化dp+分治)

description 点击查看题目 solution code 设dpi,jdp_{i,j}dpi,j​&#xff1a;把前iii个数划分jjj段的最小花费&#xff0c;wi,jw_{i,j}wi,j​&#xff1a;[i,j][i,j][i,j]划分为一段的花费 dpi,jmin(dp[k][j−1]w[k1][i])&#xff0c;k<idp_{i,j}min(dp[k][j-1]w[k1][i…

YbOJ-网格序列【拉格朗日插值】

正题 题目大意 有一个nmn\times mnm的网格&#xff0c;在上面填上[1,k][1,k][1,k]的数字&#xff0c;定义两个长度为nnn的序列ai,bia_i,b_iai​,bi​分别表示每一行/每一列的最大值。 求有多少种不同的合法a,ba,ba,b对。 1≤n,m≤106,1≤k≤1091\leq n,m\leq 10^6,1\leq k\le…

CF720C Homework(构造)(暴力)

解析 本题的关键是暴力与构造结合的思想 本题一排排往上填的想法不难得出&#xff0c;但是在列数较小的时候就会GG 所以考虑在n>5&#xff0c;m<5时&#xff0c;交换n&#xff0c;m&#xff0c;显然问题还是等价的 如果nm均小于5&#xff0c;就直接暴力dfs解决 在最后的…

第十二届蓝桥杯C++赛后感

文章目录A 空间卡片直线货物摆放路径时间显示G砝码称重H杨辉三角形双向排列J括号序列注&#xff1a;有些代码忘了考试时怎么写的了&#xff0c;&#xff08;我也懒得重新写&#xff09;&#xff0c;所以很多题的代码是acwing蓝桥杯讲解里的&#xff0c;我对其进行注释和修改A 空…

SeaweedFS在.net core下的实践方案

一直对分布式的文件储存系统很感兴趣&#xff0c;最开始关注淘宝的TFS&#xff08;Taobao File System&#xff09;&#xff0c;好像搁浅了&#xff0c;官方地址无法访问&#xff0c;github上面&#xff0c;各种编译问题&#xff0c;无意间发现了SeaweedFS链接seaweedfs测试了一…

[C++ STL algorithm] lower_bound、upper_bound、unique的本质

lower_bound&#xff1a;返回第一个大于等于查找值的地址upper_bound&#xff1a;返回第一个严格大于查找值的地址 使用这两个函数需要的头文件 #include <algorithm> using namespace std;要求数组必须是有序/单调的 lower_bound lower_bound( a 1, a n 1, x );意…

蓝桥杯 I.双向排序

题目链接 题解&#xff1a; 比赛时就直接写了一个暴力sort交上&#xff0c;能骗一点分是一点 昨晚看了acwing的讲解&#xff0c;现在结合我的思路更新正解 题目中设计两个操作&#xff0c;一个是选定前x个数&#xff0c;使其降序&#xff0c;另一个是选定后y个数&#xff0c…

YbtOJ-交换游戏【树链剖分,线段树合并】

正题 题目大意 给出两棵树&#xff0c;对于第一棵树的每一条边(x,y)(x,y)(x,y)询问有多少条在第二棵树上的边(u,v)(u,v)(u,v)与其交换&#xff08;连接的序号相同&#xff09;后两棵树依旧是一棵树。 1≤n≤21051\leq n\leq 2\times 10^51≤n≤2105 解题思路 先只考虑一棵树的…

模板:树状数组二分

所谓树状数组二分&#xff0c;就是在树状数组上进行二分 &#xff08;逃&#xff09; 解析 很巧妙 我们都知道可以在线段树上利用其本身平衡二叉的性质进行二分&#xff0c;很多时候能剩下一个log 但是树状数组其实也是可以二分的 说是二分&#xff0c;其实更像倍增 毕竟不…

微软收购Citus Data | 再次肯定对开源的承诺,并加速了Azure PostgreSQL的性能和扩展...

作者&#xff1a;Rohan Kumar 翻译&#xff1a;周宝峰 从左到右&#xff1a;微软开源关系数据库总经理Sudhakar Sannakkayala&#xff0c;Citus Data首席技术官兼联合创始人Ozgun Erdogan&#xff0c;Citus Data首席执行官兼联合创始人Umur Cubukcu&#xff0c;Citus Data工…