【刷题】洛谷 P4319 变化的道路
题目描述
小 w 和小 c 在 H 国,近年来,随着 H 国的发展,H 国的道路也在不断变化着
根据 H 国的道路法,H 国道路都有一个值 \(w\) ,表示如果小 w 和小 c 通过这条道路,那么他们的 L 值会减少 \(w\) ,但是如果小 w 和 小 c 在之前已经经过了这条路,那么他们的 L 值不会减少
H 国有 \(N\) 个国家,最开始 H 国有 \(N-1\) 条道路,这 \(N-1\) 条道路刚好构成一棵树
小 w 将和小 c 从 H 国的城市 1 出发,游览 H 国的所有城市,总共游览 32766 天,对于每一天,他们都希望游览结束后 L 值还是一个正数, 那么他们出发时 L 值至少为多少
H 国的所有边都是无向边,没有一条道路连接相同的一个城市
输入输出格式
输入格式:
输入第 1 行,一个整数 \(N\)
输入第 2 至第 \(N\) 行,每行三个正整数 \(u, v, w\) ,表示城市 \(u\) 与城市 \(v\) 有一条值为 \(w\) 道路
输入第 \(N+1\) 行,一个整数 \(M\) ,表示 H 国有 \(M\) 条正在变化的道路
输入第 \(N+2\) 行到第 \(N+M+1\) 行,每行 5 个整数 \(u, v, w, l, r\) ,表示城市 \(u\) 到城市 \(v\) 有一条值为 \(w\) 的道路, 这条道路存在于第 \(l\) 天到第 \(r\) 天
输出格式:
输出共 32766 行,第 \(i\) 行表示第 \(i\) 天游览的 L 值至少为多少
输入输出样例
输入样例#1:
4
1 3 3
3 4 4
2 4 5
3
1 2 1 1 2
2 3 8 2 3
3 4 2 1 1
输出样例#1:
7
9
13
由于版面原因,仅显示三行,接下来32763行都是13
说明
第一天,选择 1 -(1)> 2 -(0)> 1 -(3)> 3 -(2)> 4,L 值总共减少了 6,所以 L 值至少为 7
第二天,选择 1 -(1)> 2 -(0)> 1 -(3)> 3 -(4)> 4,L 值总共减少了 8,所以 L 值至少为 9
第三天及之后,选择 1 -(3)> 3 -(4)> 4 -(5)> 2,L 值总共减少了 12,所以 L 值至少为 13
subtask1 : 15分,\(N = 100, rm = 233\)
subtask2 : 15分,\(N = 1000, rm = 2333\)
subtask3 : 20分,\(N = 49998, rm = 32766, l = r\)
subtask4:20分,\(N = 49999, rm = 32766, r = rm\)
subtask5:30分,\(N = 50000, rm = 32766\)
对于subtask3 : \(M = rm\) ,对于其他subtask:\(M=3\times rm\)
对于所有数据 : \(1\leq N\leq 50000, 1\leq l\leq r\leq rm\leq 32766, 1\leq w\leq 10^9\)
题解
又是一道LCT与其它数据结构结合的题目
肯定离线做,怎么离线?时间线段树分治
考虑线段树,一条边在 \(l\) 到 \(r\) 中出现,就在线段树中 \(l\) 到 \(r\) 的区间加上这条边
最后访问线段树的每个叶子节点,然后往下递归的时候如果区间上有边的标记,就加边;到叶子节点的时候,算答案;回溯的时候,把在这个区间内加的边又删去。(当然,这个线段树虽然要打标记,但是不会有pushdown的)
然后就做完了
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=200000+10,inf=0x3f3f3f3f;
int n,m,scnt;
ll ans;
struct edge{
int u,v,w;
};
edge side[MAXN];
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
int ch[MAXN][2],fa[MAXN],rev[MAXN],stack[MAXN],cnt,Mx[MAXN],id[MAXN],val[MAXN];
inline void init()
{
memset(Mx,-inf,sizeof(Mx));
memset(val,-inf,sizeof(val));
}
inline bool nroot(int x)
{
return lc(fa[x])==x||rc(fa[x])==x;
}
inline void reverse(int x)
{
std::swap(lc(x),rc(x));
rev[x]^=1;
}
inline void pushup(int x)
{
Mx[x]=val[x],id[x]=x;
if(Mx[lc(x)]>Mx[x])Mx[x]=Mx[lc(x)],id[x]=id[lc(x)];
if(Mx[rc(x)]>Mx[x])Mx[x]=Mx[rc(x)],id[x]=id[rc(x)];
}
inline void pushdown(int x)
{
if(rev[x])
{
if(lc(x))reverse(lc(x));
if(rc(x))reverse(rc(x));
rev[x]=0;
}
}
inline void rotate(int x)
{
int f=fa[x],p=fa[f],c=(rc(f)==x);
if(nroot(f))ch[p][rc(p)==f]=x;
fa[ch[f][c]=ch[x][c^1]]=f;
fa[ch[x][c^1]=f]=x;
fa[x]=p;
pushup(f);
pushup(x);
}
inline void splay(int x)
{
cnt=0;
stack[++cnt]=x;
for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
while(cnt)pushdown(stack[cnt--]);
for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
pushup(x);
}
inline void access(int x)
{
for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
}
inline void makeroot(int x)
{
access(x);splay(x);reverse(x);
}
inline void split(int x,int y)
{
makeroot(x);access(y);splay(y);
}
inline void link(int x,int y)
{
makeroot(x);fa[x]=y;
}
inline void cut(int x,int y)
{
split(x,y);fa[x]=lc(y)=0;pushup(y);
}
};
LCT T1;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
#define Mid ((l+r)>>1)
#define lson rt<<1,l,Mid
#define rson rt<<1|1,Mid+1,r
struct SEG{
std::vector<int> V[MAXN];
inline void Update(int rt,int l,int r,int L,int R,int k)
{
if(L<=l&&r<=R)V[rt].push_back(k);
else
{
if(L<=Mid)Update(lson,L,R,k);
if(R>Mid)Update(rson,L,R,k);
}
}
inline void Query(int rt,int l,int r)
{
std::stack< std::pair<int,int> > S;
for(register int i=0,limit=V[rt].size();i<limit;++i)
{
int u=side[V[rt][i]].u,v=side[V[rt][i]].v,w=side[V[rt][i]].w,sn=V[rt][i]+n;
T1.split(u,v);
if(w<T1.Mx[v])
{
ans-=T1.Mx[v]-w;
int so=T1.id[v];
T1.cut(so,side[so-n].u);T1.cut(so,side[so-n].v);
S.push(std::make_pair(so,1));
T1.val[sn]=w;
T1.link(sn,u);T1.link(sn,v);
S.push(std::make_pair(sn,0));
}
}
if(l==r)write(ans+1,'\n');
else Query(lson),Query(rson);
while(!S.empty())
{
std::pair<int,int> now=S.top();
S.pop();
int sn=now.first;
if(!now.second)T1.cut(side[sn-n].u,sn),T1.cut(side[sn-n].v,sn),ans-=side[sn-n].w;
else T1.link(side[sn-n].u,sn),T1.link(side[sn-n].v,sn),ans+=side[sn-n].w;
}
}
};
SEG T2;
#undef Mid
#undef lson
#undef rson
int main()
{
read(n);
for(register int i=1;i<n;++i)
{
int u,v,w,sn=i+n;
read(u);read(v);read(w);
side[++scnt]=(edge){u,v,w};
ans+=w;
T1.val[sn]=w;
T1.link(sn,u);T1.link(sn,v);
}
read(m);
for(register int i=1;i<=m;++i)
{
int u,v,w,l,r;
read(u);read(v);read(w);read(l);read(r);
side[++scnt]=(edge){u,v,w};
T2.Update(1,1,32766,l,r,scnt);
}
T2.Query(1,1,32766);
return 0;
}
【刷题】洛谷 P4319 变化的道路的更多相关文章
- 洛谷 P4319 变化的道路 解题报告
P4319 变化的道路 题目描述 小 w 和小 c 在 H 国,近年来,随着 H 国的发展,H 国的道路也在不断变化着 根据 H 国的道路法,H 国道路都有一个值 \(w\),表示如果小 w 和小 c ...
- 洛谷P4319 变化的道路
题意:给定图,每条边都有一段存在时间.求每段时间的最小生成树. 解:动态MST什么毒瘤...洛谷上还是蓝题... 线段树分治 + lct维护最小生成树. 对时间开线段树,每条边的存在时间在上面会对应到 ...
- 洛谷P1462 通往奥格瑞玛的道路(二分+spfa,二分+Dijkstra)
洛谷P1462 通往奥格瑞玛的道路 二分费用. 用血量花费建图,用单源最短路判断 \(1\) 到 \(n\) 的最短路花费是否小于 \(b\) .二分时需要不断记录合法的 \(mid\) 值. 这里建 ...
- 洛谷P1462-通往奥格瑞玛的道路-二分+最短路
洛谷P1462-通往奥格瑞玛的道路 题目描述 在艾泽拉斯,有\(n\)个城市.编号为\(1,2,3,...,n\). 城市之间有\(m\)条双向的公路,连接着两个城市,从某个城市到另一个城市,会遭到联 ...
- 【题解】洛谷P2296 [NOIP2014TG] 寻找道路(SPFA+DFS)
题目来源:洛谷P2296 思路 一开始看还以为是一道水题 虽然本来就挺水的 本道题的难点在于如何判断是否路径上的点都会直接或者间接连着终点 我们需要在一开始多建一个反向图 然后从终点DFS回去 把路径 ...
- 洛谷 P1462 通往奥格瑞玛的道路
洛谷 题意:要求在限定油耗内,求最小花费的最大值. 求最小值最大很容易想到二分答案.所以我们往二分的方向去想. 我们二分一个费用,然后要保证到终点时满足限定油耗,所以跑最短路. 不过松弛条件要改一下: ...
- 2018.10.30 一题 洛谷4660/bzoj1168 [BalticOI 2008]手套——思路!问题转化与抽象!+单调栈
题目:https://www.luogu.org/problemnew/show/P4660 https://www.lydsy.com/JudgeOnline/problem.php?id=1168 ...
- 【洛谷P4319】 变化的道路 线段树分治+LCT
最近学了一下线段树分治,感觉还蛮好用... 如果正常动态维护最大生成树的话用 LCT 就行,但是这里还有时间这一维的限制. 所以,我们就把每条边放到以时间为轴的线段树的节点上,然后写一个可撤销 LCT ...
- 洛谷 P1462 通往奥格瑞玛的道路 解题报告
P1462 通往奥格瑞玛的道路 题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡 ...
随机推荐
- python继承与多继承
1.类与对象里的父类与子类(继承): 类的继承主要是指自子类对于之前父类的方法的继承,如果子类里面写了父类里的方法,则它会将父类里的方法覆盖掉,从而不能再调用到父类的方法. 2.为了解决父类与子类里的 ...
- Unity优化方向——优化Unity游戏中的图形渲染(译)
CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...
- oracle数据库之rownum和rowid用法
Rownum 和 Rowid是Oracle数据库所特有的,通过他们可以查询到指定行数范围内的数据记录. 以下通过例子讲解: -- 为了方便,首先,查找dept表中的所有. select deptn ...
- 剑指offer试题(PHP篇三)
21.栈的压入.弹出序列 题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4 ...
- Vue Cli 中使用 Karma / Chrome 执行样式相关单元测试
在 GearCase 开源项目 中,我使用了 Vue Cli 的默认测试框架.因此和样式相关的东西,都无法进行测试.因为它并不类似于无头浏览器,而是存在于虚拟内存之中. 现状 在如下 button.s ...
- Azure web site和web job的config文件加密方式
1.分析 由于Azure Web AppService平台的特殊性,所以在C#中原先的config加密方法DataProtectionConfigurationProvider和RSAProtecte ...
- 初学node.js-npm使用(2)
1.安装Node封装模块 安装Node封装模块很重要,因为开发项目中会用到各种各样的功能,这时就需要去下载开源的模块 使用npm install <module_name> module_ ...
- 03_set slice的时间复杂度
set slice O(n+k) 使用切片赋值来解释set slice的时间复杂度 (1) 对li[0:3]赋值首先会删除1,2,3,空出来的位置被后面的元素依次向前移动填充,由del slice 得 ...
- python 拾遗
三引号 可以当做多行字符串使用.在类或者方法中用的时候,可以当做docstrings来使用.具体的规则为: 该文档字符串所约定的是一串多行字符串,其中第一行以某一大写字母开始,以句号结束.第二行为空行 ...
- [朴孝敏][Road Trip]
歌词来源:http://music.163.com/#/song?id=406907305 作曲 : Ryan S. Jhun/G'harah 'PK' Degeddingseze/Denzil Re ...