Fools and Roads CodeForces - 191C

Fools and Roads CodeForces - 191C

题意:给出一棵n个节点的树,还有树上的k条简单路径(用路径的两个端点u和v表示),求树上的各条边被这些简单路径经过的总次数。

方法:

一开始想了很久..想要在倍增求lca的同时统计边经过的次数..然而发现这样子可以统计,但是统计的值拆不开...没有办法在合适时间内得到答案...并没有思路..

想了很久发现,这其实就是个简单的树上差分,只要记录一下每个节点i到根节点路径上所有边都需要加的权值sum[i]就行了。

对于每一组(u,v),题意操作转化为sum[u]++,sum[v]++,sum[lca(u,v)]-=2。

最后用一遍dfs把sum拆开,这个"树上前缀和"是可以O(n)拆开的。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> P;
vector<LL> v[100100];
vector<P> vv;
LL T,n,ne,k;
LL deep[100100],anc[100100][17],log2n,sum[100100],ans[100100];
void dfs(LL x,LL fa)
{
    LL i;
    anc[x][0]=fa;
    deep[x]=deep[fa]+1;
    for(i=1;i<=log2n;i++)
        anc[x][i]=anc[anc[x][i-1]][i-1];
    for(auto y:v[x])
        if(y!=fa)
            dfs(y,x);
}
LL lca(LL x,LL y)
{
    LL t,i;
    if(deep[x]<deep[y])    swap(x,y);
    for(t=deep[x]-deep[y],i=0;t>0;t>>=1,i++)
        if(t&1)    x=anc[x][i];
    if(x==y)    return x;
    for(i=log2n;i>=0;i--)
        if(anc[x][i]!=anc[y][i])
        {
            x=anc[x][i];
            y=anc[y][i];
        }
    return anc[x][0];
}
void dfs2(LL x,LL fa)
{
    for(auto y:v[x])
        if(y!=fa)
            dfs2(y,x);
    ans[x]+=sum[x];sum[fa]+=sum[x];
}
int main()
{
    LL i,x,y;
    scanf("%lld",&n);log2n=log2(n);
    for(i=1;i<n;i++)
    {
        scanf("%lld%lld",&x,&y);
        v[x].push_back(y);
        v[y].push_back(x);
        vv.push_back(P(x,y));
    }
    dfs(1,0);
    scanf("%lld",&k);
    for(i=1;i<=k;i++)
    {
        scanf("%lld%lld",&x,&y);
        sum[x]++;sum[y]++;sum[lca(x,y)]-=2;
    }
    dfs2(1,0);
    for(auto k:vv)    printf("%lld ",ans[deep[k.first]>deep[k.second]?k.first:k.second]);
    return 0;
}

原文地址:https://www.cnblogs.com/hehe54321/p/cf-191c.html

时间: 2024-10-09 04:12:17

Fools and Roads CodeForces - 191C的相关文章

Codeforces 191C Fools and Roads(树链剖分)

题目链接:Codeforces 191C Fools and Roads 题目大意:给定一个N节点的数,然后有M次操作,每次从u移动到v,问说每条边被移动过的次数. 解题思路:树链剖分维护边,用一个数组标记即可,不需要用线段树. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1e5 + 5; int N, Q, ne, fir

CF 191C Fools and Roads lca 或者 树链剖分

They say that Berland has exactly two problems, fools and roads. Besides, Berland has n cities, populated by the fools and connected by the roads. All Berland roads are bidirectional. As there are many fools in Berland, between each pair of cities th

CodeForces 191C Fools and Roads 树上的前缀和 LCA

题目链接:点击打开链接 题意: 给定n个点的树. 下面m个操作,每次给一条路径上的边都染一次. 最后问:每个边被染色的次数. 和去年网赛的一道差不多,就是类似前缀和的做法, 我们在某个点+1然后从叶子节点到根节点求一个前缀和,这样某个点加1就相当于某个点到根的路径都加了1. 所以当我们给[u,v]染色时就 sum[u]++; sum[v]++; sum[LCA(u,v)]-=2; 再把重复的部分减掉即可. 最后求个前缀和. #include <cstdio> #include <vect

Codeforces 191 C Fools and Roads (树链剖分)

题目链接~~> 做题感悟:这题在做了HDU 5044后就感觉很简单了. 解题思路: 先树链剖分一下,把树剖分成链,因为最后全是询问,so~可以线性操作.经过树链剖分后,就会形成许多链,但是每条边都有编号,相当于一个数组进行线性操作,这样,如果在 u  ~ v 去都增加 1 ,那么可以让 sum [ u ] += 1 ; sum [ v + 1 ] -= 1 ; 这里假设 v 的编号大.最后的时候只要从后往前遍历一次就可以了,得到所有的结果.明白这点后再加上树链剖分的思想就可以解决了. 代码: #

Codeforces 191 C Fools and Roads (树链拆分)

主题链接~~> 做题情绪:做了HDU 5044后就感觉非常easy了. 解题思路: 先树链剖分一下,把树剖分成链,由于最后全是询问,so~能够线性操作.经过树链剖分后,就会形成很多链,可是每条边都有编号,相当于一个数组进行线性操作,这样.如果在 u  ~ v 去都添加 1 .那么能够让 sum [ u ] += 1 ; sum [ v + 1 ] -= 1 ; 这里如果 v 的编号大. 最后的时候仅仅要从后往前遍历一次就能够了.得到全部的结果.明确这点后再加上树链剖分的思想就能够攻克了. 代码:

【CF】121 Div.1 C. Fools and Roads

题意是给定一棵树.同时,给定如下k个查询: 给出任意两点u,v,对u到v的路径所经过的边进行加计数. k个查询后,分别输出各边的计数之和. 思路利用LCA,对cnt[u]++, cnt[v]++,并对cnt[LCA(u, v)] -= 2.然后dfs求解各边的计数. 1 /* 191C */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #inc

CF191C Fools and Roads

题目链接:https://www.luogu.com.cn/problem/CF191C https://codeforces.com/problemset/problem/191/C 题意: 给你一棵树,然后给你m对点,将每对点之间的最短路径上每条边权值+1,求操作完成后每条边的权值. 方法: p[s]++,p[t]++,p[lca(s,t)]-=2 用倍增算法计算LCA 代码: #include <bits/stdc++.h> #define LL long long using name

CodeForces 191C 树链剖分 第4遍

非常无奈,模板重新无奈的打错了.. 只是,非常快便找到了.. 题意:给一些边,有一些操作,每次操作,都要在这些边上加上1,求每一个边的边权.. #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; #define lson id << 1 #define rson id << 1|1 const in

New Roads CodeForces - 746G (树,构造)

大意:构造n结点树, 高度$i$的结点有$a_i$个, 且叶子有k个. 先确定主链, 然后贪心放其余节点. #include <iostream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #include <map> #include <queue> #include <string> #include &l