Educational Codeforces Round 54 (Rated for Div. 2) DE
D 给出一个无向图,需要删去一些边,想知道最后能有多少个点到1的距离还是过去那么短
如果求一个最短路,然后从删边的角度看,看起来很难做,但是如果从零开始加边就会有做法,如同prim那样,先加入和1直接相连的边,这条边必定是cost最小的,因为只有这样才能保证连接的点是最短路,这也是prim的思想。
当加入一个点a后,需要将a相连的边也加入考虑,假设有1->a a->b ,由于1->a已经被我们选了,那么假装有边1->b,在进行一下第一轮的选择,如果1->b被选了,那么其实选的是a->b,这样会发现,及时最后能留许多边,我们也只会选择n-1条,一个图上虽然有很多边,但是求完单源最短路后,一定有某种方法将这些最短路用一棵树来表示。
看起来这个做法是prim的变种。。因为完全是把最短路当作树来考虑的,但是写完后想了一下。。这个做法一般被称为堆优化的dij。。。
struct node{
L v;//�����
L c;//��������
L bh ;
node(L _v=0,L _c=0,L tp=0):v(_v),c(_c),bh(tp){};
bool operator <(const node &r)const{
return c>r.c;
}
};
priority_queue<node>q ; vector<node> w[300050] ;
vector<int>ans ;
L d[300050] ; int main () {
L n , m , k ;
cin >> n >> m >> k ;
for(L i = 1 ; i <= m ; i ++ ) {
L u , v , c ;
cin >> u >> v >> c ;
w[u].pb(node(v,c,i)) ;
w[v].pb(node(u,c,i)) ;
}
L us = 0 ;
memset(d , -1 , sizeof(d)) ;
d[1] = 0;
for(L i = 0 ; i < w[1].size() ; i ++ ) {
q.push(w[1][i]) ;
}
while(!q.empty()) {
node f = q.top() ; q.pop() ;
if(d[f.v] != -1) continue ;
if(us >= k) break ;
us ++ ;
ans.pb(f.bh) ;
d[f.v] = f.c ;
for(L i = 0 ; i < w[f.v].size() ; i ++ ) {
node tp ;
tp.v = w[f.v][i].v ;
tp.c = f.c + w[f.v][i].c ;
tp.bh = w[f.v][i].bh ;
q.push(tp) ;
}
}
cout << us << endl ;
sort(ans.begin() , ans.end()) ;
show(ans) ;
L z = 0 ;
}
E 给出一棵有根树,初始点权为0,每次操作将点v的0~d代孩子权值+x,最后输出每个点的权值
dfs序之后,每个点都可以被看作一个二维平面上的点,(dfsid,depth),那么其实就是矩形加和,最后统一询问点权
# 有很多办法可以做,不过因为矩形范围太大 3e5,使用KDT来写,但是wa了。。寻找bug 后续 我没找出来啊。。。绝望
矩阵加和辣么经典。。于是采用线段树来写,思路是把所有的(l,r,up,dow,val)的加和拆分成(l,up,dow,val)和(r+1,up,dow,-val),从左到右维护一个线段树即可
外国选手不流行lowbit,倒是造出了玄妙的东西,支持单点加,区间求和。
const L mn = 300050 ;
L ans[mn] ;
L ll[mn] , rr[mn] , pre[mn] , d[mn];
L tot ; vector<L > G[mn] ;
vector<pii > Q[mn] ; void dfs(L u,L p) {
tot ++ ;
if (p == -1) d[u] = 1 ;
ll[u] = tot ;
pre[tot] = u ;
for(L i = 0; i < G[u].size() ; i ++ ) {
L v = G[u][i] ;
if(v != p) {
d[v] = d[u] + 1 ;
dfs(v , u) ;
}
}
rr[u] = tot ;
} L su[mn * 4] ;
L ma[mn * 4] ;
void dow(L ro,L l,L r) {
if(l == r) return ;
ma[ro*2] += ma[ro] ;
ma[ro*2+1] += ma[ro] ;
su[ro*2] += ma[ro] ;
su[ro*2+1] += ma[ro] ;
ma[ro] = 0 ;
}
void upda(L ro,L l,L r,L ql,L qr,L x) {
if (ql <= l && qr >= r) {
su[ro] += x ;
ma[ro] += x ;
return ;
}
dow(ro,l,r) ;
L mid = (l + r) / 2 ;
if(ql <= mid) upda(ro*2,l,mid,ql,qr,x) ;
if(qr >= mid + 1) upda(ro*2+1,mid+1,r,ql,qr,x) ;
su[ro] = su[ro*2] + su[ro*2+1] ;
}
L query(L ro,L l,L r,L pos) {
if(l == r) return su[ro] ;
L mid = (l + r) / 2 ;
dow(ro,l,r) ;
if(pos <= mid) return query(ro*2,l,mid,pos) ;
else return query(ro*2+1,mid+1,r,pos) ;
} const L T = 1 << 19 ; L c[2*T+50] ;
void add(L x,L v) {
x += T ;
while(x) {
c[x] += v;
x /= 2 ;
}
}
L ask(L l,L r) {
L res = 0 ;
l += T , r += T ;
while(l < r) {
if (l & 1) {
res += c[l] ;
}
if (!(r & 1)) {
res += c[r] ;
}
l = (l + 1) >> 1 ;
r = (r - 1) >> 1 ;
}
if (l == r)
res += c[r] ;
return res ;
} int main () {
L n ; cin >> n ;
rep(i,1,n-1) {
L u, v ; // cin >> u >> v ;
scanf("%lld%lld" , &u, &v) ;
G[u].pb(v) ;
G[v].pb(u) ;
}
tot = 0 ;
dfs(1,-1) ; L qnum ; cin >> qnum ;
while(qnum -- ) {
L xi , di , vi ;
// cin >> vi >> di >> xi ;
scanf("%lld%lld%lld" , &vi , &di , &xi) ;
L dep = di + d[vi] ;
dep = min(dep , n) ;
Q[ ll[vi] ].push_back(make_pair(dep , xi)) ;
Q[ rr[vi] + 1 ].push_back(make_pair(dep , -xi)) ;
}
flc(c,0) ;
for(L i = 1 ; i <= n ; i ++ ) {
for(L j = 0 ; j < Q[i].size() ; j ++ ) {
pii p = Q[i][j] ;
upda(1,1,n,1,p.first,p.second) ;
// add(p.first,p.second) ;
}
ans[ pre[i] ] = query(1,1,n,d[ pre[i] ]) ;
// ans[ pre[i] ] = ask(d[ pre[i] ] , n) ;
}
for(L i = 1 ; i <= n ; i ++ ) {
printf("%lld" , ans[i]) ;
if(i == n) printf("\n") ; else printf(" ") ;
}
}
--- 2020.2.3 ---
因为没事干,所以看了一眼自己以前的博客,看看是否智商降低了,发现这个题有简单的做法,将有深度限制的子树加减转化成二维点跑矩阵加减其实是KDT题集里面学到的,然后陷入了数据结构的误区
将树上点的值以dfsid作为数组存储,会发现每次操作是在[l,r]区间进行一次有[depl,depr]的限制加法,可以在l点加上+, 在r点加上-的操作
从1~n扫一遍,维护一个线段树或树状数组,就行了。
Educational Codeforces Round 54 (Rated for Div. 2) DE的更多相关文章
- Educational Codeforces Round 59 (Rated for Div. 2) DE题解
Educational Codeforces Round 59 (Rated for Div. 2) D. Compression 题目链接:https://codeforces.com/contes ...
- Educational Codeforces Round 54 (Rated for Div. 2) D:Edge Deletion
题目链接:http://codeforces.com/contest/1076/problem/D 题意:给一个n个点,m条边的无向图.要求保留最多k条边,使得其他点到1点的最短路剩余最多. 思路:当 ...
- Educational Codeforces Round 54 [Rated for Div. 2] (CF1076)
第一次在宿舍打CF 把同宿舍的妹子吵得不行... 特此抱歉QAQ A 题意:给定一个字符串, 最多删掉一个字符,使得剩余字符串字典序最小 n<=2e5 当然"最多"是假的 删 ...
- Educational Codeforces Round 54 (Rated for Div. 2) Solution
A - Minimizing the String solved 题意:给出一个字符串,可以移掉最多一个字符,在所有可能性中选取一个字典序最小的. 思路:显然,一定可以移掉一个字符,如果移掉的字符的后 ...
- Educational Codeforces Round 54 (Rated for Div. 2) ABCD
A. Minimizing the String time limit per test 1 second memory limit per test 256 megabytes Descriptio ...
- Educational Codeforces Round 54 (Rated for Div. 2) D Edge Deletion (SPFA + bfs)
题目大意:给定你一个包含n个点m条边的无向图,现在最多在图中保留k条边,问怎么删除多的边,使得图中良好的节点数最多,求出保留在图中的边的数量和编号. 良好的节点定义为:删除某条边后该点到点1的最短距离 ...
- Educational Codeforces Round 72 (Rated for Div. 2)-D. Coloring Edges-拓扑排序
Educational Codeforces Round 72 (Rated for Div. 2)-D. Coloring Edges-拓扑排序 [Problem Description] 给你 ...
- Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship
Problem Educational Codeforces Round 60 (Rated for Div. 2) - C. Magic Ship Time Limit: 2000 mSec P ...
- Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems(动态规划+矩阵快速幂)
Problem Educational Codeforces Round 60 (Rated for Div. 2) - D. Magic Gems Time Limit: 3000 mSec P ...
随机推荐
- PHP 支持8种基本的数据类型。
四种标量类型:boolean (布尔型):这是最简单的类型,只有两种取值,可以为 TRUE/true 或 FALSE/false ,不区分大小写.详细请查看:PHP布尔类型(boolean)integ ...
- 并发编程 - 进程 - 1.队列的使用/2.生产者消费者模型/3.JoinableQueue
1.队列的使用: 队列引用的前提: 多个进程对同一块共享数据的修改:要从硬盘读文件,慢,还要考虑上锁: 所以就出现了 队列 和 管道 都在内存中(快): 队列 = 管道 + 上锁 用队列的目的: 进程 ...
- 剑指Offer——树的子结构
题目描述: 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 分析: 先匹配到A的某个结点和B的根相同,然后往下继续匹配.不匹配则递归匹配左右子树. 代码: ...
- css冲突2 要关闭的css在项目代码以外,但是是通过<link>标签引入的css(例如bootstrap):解决方法,在APP.css中使用全局样式
css冲突,导致html字体过小. 通过浏览器检查发现,导致字体过小的css来自bootstrap. 现要关闭bootstrap的css: 直接在APP.css中添加: html{ font-size ...
- AttributeError: 'NoneType' object has no attribute 'append'
大多数是这个原因: gongzi = [] for p in [1,2,3]: gongzi = gongzi.append(p) #改为如下即可 gongzi = [] for p in [1,2, ...
- 关闭linux的防火墙
有两道防火墙 第一道 iptables -L iptables -F systemctl disable firewalld 第二道 [root@python3 ~]# getenforce Enfo ...
- 聊聊高并发(三十四)Java内存模型那些事(二)理解CPU快速缓存的工作原理
在上一篇聊聊高并发(三十三)从一致性(Consistency)的角度理解Java内存模型 我们说了Java内存模型是一个语言级别的内存模型抽象.它屏蔽了底层硬件实现内存一致性需求的差异,提供了对上层的 ...
- Mac电脑下-nodejs安装卸载升级
一.Mac 安装nodejs: 1:brew install node 2:官网上下载指定版本(.pkg)双击安装 二.Mac 卸载nodejs: 1: brew的安装方式的卸载: brew un ...
- HTML5游戏开发系列教程6(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-6/ 这是我们最新一篇HTML5游戏开发系列文章.我们将继续使用c ...
- Java并发编程实战4章
第4章主要介绍如何构造线程安全类. 在设计线程安全类的过程中,需要包含以下三个基本要素: 找出构成对象状态的所有变量. 找出约束状态变量的不变性条件. 建立对象状态的并发访问管理策略. 构造线程安全类 ...