P3313 [SDOI2014] 旅行(分块做法)

2024-09-04 12:36

本文主要是介绍P3313 [SDOI2014] 旅行(分块做法),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

~~~~~      P3313 [SDOI2014] 旅行 ~~~~~      总题单链接

思路

~~~~~      遇到这种树上路径问题,就考虑用重链剖分转为区间问题。

~~~~~      问题转换为了:给定一个区间和 k k k,求这个区间内信仰为 k k k 的城市的 权值和 或 最大权值。

~~~~~      这个问题也可以用动态开点线段树解决(现在不会,以后再讲),但今天的主角是分块。

~~~~~      查询就是一般的分块查询。而修改,因为要求最大值,所以直接 O ( n ) O(\sqrt{n}) O(n ) 暴力修改即可。

代码

#include<bits/stdc++.h>
#define ll long long
#define fir first
#define sec second
#define endl '\n'
using namespace std;vector<ll>eg[100005];
pair<ll,ll>cpo[100005];ll n,Q,id[100005],di[100005];class CLK{public:ll B,pos[100005];struct BLK{ll L,R,sm[100005],mx[100005];}blk[350];void init(){B=sqrt(n);for(ll i=1;i<=B;i++){blk[i].L=(i-1)*B+1,blk[i].R=i*B;for(ll j=blk[i].L;j<=blk[i].R;j++){pos[j]=i;blk[i].sm[cpo[di[j]].sec]+=cpo[di[j]].fir;blk[i].mx[cpo[di[j]].sec]=max(blk[i].mx[cpo[di[j]].sec],cpo[di[j]].fir);}}if(blk[B].R<n){B++;blk[B].L=blk[B-1].R+1;blk[B].R=n;for(ll j=blk[B].L;j<=blk[B].R;j++){pos[j]=B;blk[B].sm[cpo[di[j]].sec]+=cpo[di[j]].fir;blk[B].mx[cpo[di[j]].sec]=max(blk[B].mx[cpo[di[j]].sec],cpo[di[j]].fir);}}}inline void clear(ll p){for(ll j=blk[p].L;j<=blk[p].R;j++){blk[p].sm[cpo[di[j]].sec]=0;blk[p].mx[cpo[di[j]].sec]=0;}}inline void adsmx(ll p){for(ll j=blk[p].L;j<=blk[p].R;j++){blk[p].sm[cpo[di[j]].sec]+=cpo[di[j]].fir;blk[p].mx[cpo[di[j]].sec]=max(blk[p].mx[cpo[di[j]].sec],cpo[di[j]].fir);}}inline void modify_1(ll p,ll k){clear(pos[id[p]]);cpo[p].fir=k;adsmx(pos[id[p]]);}inline void modify_2(ll p,ll k){clear(pos[id[p]]);cpo[p].sec=k;adsmx(pos[id[p]]);}inline ll query_1(ll x,ll y,ll k){ll res=0;if(pos[x]==pos[y]){for(ll i=x;i<=y;i++)if(cpo[di[i]].sec==k)res+=cpo[di[i]].fir;return res;}for(ll i=x;i<=blk[pos[x]].R;i++)if(cpo[di[i]].sec==k)res+=cpo[di[i]].fir;for(ll i=y;i>=blk[pos[y]].L;i--)if(cpo[di[i]].sec==k)res+=cpo[di[i]].fir;for(ll i=pos[x]+1;i<pos[y];i++)res+=blk[i].sm[k];return res;}inline ll query_2(ll x,ll y,ll k){ll res=0;if(pos[x]==pos[y]){for(ll i=x;i<=y;i++)if(cpo[di[i]].sec==k)res=max(res,cpo[di[i]].fir);return res;}for(ll i=x;i<=blk[pos[x]].R;i++)if(cpo[di[i]].sec==k)res=max(res,cpo[di[i]].fir);for(ll i=y;i>=blk[pos[y]].L;i--)if(cpo[di[i]].sec==k)res=max(res,cpo[di[i]].fir);for(ll i=pos[x]+1;i<pos[y];i++)res=max(res,blk[i].mx[k]);return res;}}clk;class TRE{public:ll dep[100005],siz[100005],tot;ll son[100005],fas[100005],top[100005];void dfs_1(ll fa,ll p){dep[p]=dep[fa]+1;siz[p]=1;fas[p]=fa;for(ll v:eg[p]){if(v==fa)continue;dfs_1(p,v);siz[p]+=siz[v];if(siz[son[p]]<siz[v])son[p]=v;}}void dfs_2(ll p,ll tpo){id[p]=++tot;di[tot]=p;top[p]=tpo;if(son[p])dfs_2(son[p],tpo);for(ll v:eg[p]){if(v==fas[p]||v==son[p])continue;dfs_2(v,v);}}void init(){dfs_1(0,1);dfs_2(1,1);clk.init();}inline ll query_1(ll x,ll y,ll k){ll res=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);res+=clk.query_1(id[top[x]],id[x],k);x=fas[top[x]];}if(dep[x]>dep[y])swap(x,y);res+=clk.query_1(id[x],id[y],k);return res;}inline ll query_2(ll x,ll y,ll k){ll res=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);res=max(res,clk.query_2(id[top[x]],id[x],k));x=fas[top[x]];}if(dep[x]>dep[y])swap(x,y);res=max(res,clk.query_2(id[x],id[y],k));return res;}}tre;signed main(){ios::sync_with_stdio(false);cin>>n>>Q;for(ll i=1;i<=n;i++)cin>>cpo[i].fir>>cpo[i].sec;for(ll i=1;i<n;i++){ll x,y;cin>>x>>y;eg[x].push_back(y);eg[y].push_back(x);}tre.init();while(Q--){char op;ll x,y;cin>>op>>op>>x>>y;if(op=='C')clk.modify_2(x,y);if(op=='W')clk.modify_1(x,y);if(op=='S')cout<<tre.query_1(x,y,cpo[x].sec)<<endl;if(op=='M')cout<<tre.query_2(x,y,cpo[x].sec)<<endl;}return 0;
}

这篇关于P3313 [SDOI2014] 旅行(分块做法)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1136039

相关文章

社交平台找旅游搭子一起旅行靠谱吗?答案是不要太爽!

哈喽小伙伴们,今天要跟大家分享一个超级棒的小程序——咕哇找搭子!作为一个热爱自由行的人,最头疼的就是找不到志同道合的小伙伴。但自从用了这个咕哇小程序后,一切都变得简单又充满乐趣啦!🎉 上个月,我计划去云南旅行,就试着在咕哇上发布了我的行程信息。没想到很快就收到了几位朋友的回应,其中一位叫小莲的朋友特别投缘。我们不仅目的地一样,就连兴趣爱好都出奇地相似,于是我们就决定一起出发啦!👭

旅行商问题 | Matlab基于混合粒子群算法GA-PSO的旅行商问题TSP

目录 效果一览基本介绍建模步骤程序设计参考资料 效果一览 基本介绍 混合粒子群算法GA-PSO是一种结合了遗传算法(Genetic Algorithm, GA)和粒子群优化算法(Particle Swarm Optimization, PSO)的优化算法。在解决旅行商问题(Traveling Salesman Problem, TSP)时,这种混合算法可以结合两种算法的优点

Spring Boot实现大文件分块上传

1.分块上传使用场景 大文件加速上传:当文件大小超过100MB时,使用分片上传可实现并行上传多个Part以加快上传速度。 网络环境较差:网络环境较差时,建议使用分片上传。当出现上传失败的时候,您仅需重传失败的Part。 文件大小不确定: 可以在需要上传的文件大小还不确定的情况下开始上传,这种场景在视频监控等行业应用中比较常见。 2.实现原理 实现原理其实很简单,核心就是客户端把大文件

【BNU】40719 Arithmetic Progressions【分块+FFT】

传送门:【BNU】40719 Arithmetic Progressions 题目分析: 用分块+FFT强行AC了这题…… 之前一直TLE……然后改了好久把姿势改的优美点了……终于过了…… 大概思路是:我们考虑分块,假设每一块的大小为S,一共分了B块然后我们分两种情况讨论: 1.第二个数在第i块,第一个数在(1~i-1)块内,第三个数在(i+1~B)块内。 2.至少两个数在同一块内。

【HDU】5213 Lucky 【分块(在线算法)】

传送门:【HDU】5213 Lucky 题目分析: 我来说一下这题的在线做法。 首先我们将区间分成 n√ \sqrt n块,用f[x][y]表示第x块的数和第y块的数相加等于K的对数,这个可以 O(nn√) O(n \sqrt n)的预处理。然后还有g[x][y]表示在第1~x块中有的大小为y的数的个数,这个的复杂度同样 O(nn√) O(n \sqrt n)。 接下来,对于每组询问,我们

贪心问题n位数删除s位94页第3种做法

// 贪心问题n位数删除s位94页第3种做法.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//2024-4-15#include <iostream>#include<string>using namespace std;void del(char n[],int b,int k,int& len){for (int i = b; b < len - k;i+

P4842 城市旅行(拆贡献 + LCT)

https://www.luogu.com.cn/problem/P4842 发现题目就是要维护一个LCT,然后我们只要把pushup写成功了就行。 那我们现在就不管LCT了,就单纯想用一棵二叉查找树怎么维护。分母是好搞的,分子我们要想点办法。 考虑右子树对左子树的贡献,我们假设处理出一个 L [ k ] L[k] L[k] 表示左子树中每个值乘以左边界的可选数量,我们现在再乘上右子树的大

最长上升子序列 二分做法

给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。 输入格式 第一行包含整数N。 第二行包含N个整数,表示完整序列。 输出格式 输出一个整数,表示最大长度。 数据范围 1≤N≤10001≤N≤1000, −109≤数列中的数≤109−109≤数列中的数≤109 输入样例: 73 1 2 1 8 5 6 输出样例: 4 二分做出的答案只有数量是最长上升子

针对大数据的种子点生长——分块生长的策略

前言   在之前的种子点生长系列中,探讨了使用三种提取图像中内容部分种子点生长算法,分别是泛洪法、扫描线法和区段法。我们知道这三种算法在空间上都需要占用三维图像的空间以及相应的位图标记表的空间。有时,我们需要处理一些体积相当大的数据,这些数据都是内存中无法放下的,如数十数百GB的数据,想要获得其中图像内容信息,一般需要对图像进行分块生长。   本文使用一种比较直接的思路对数据进行分块,然

学习笔记 ---- 数论分块(整除分块)

文章目录 算法概述引理引理 1 1 1引理 2 2 2 数论分块结论(区间右端点公式)过程 N N N 维数论分块向上取整的数论分块 例题 H ( n ) H(n) H(n)[CQOI2007] 余数求和[清华集训2012] 模积和 算法 概述 数论分块可以快速计算一些含有除法向下取整的和式(即形如 ∑ i = 1 n f ( i ) g ( ⌊ n i ⌋ ) \sum