题目大意

一棵 \(n(1\leq n\leq 2\times 10^5)\) 个节点以 \(1\) 为根的树,分别求以 \(1\sim n\) 为根的子树中有多少个节点编号连续的段。 \(T(1\leq T\leq 10)\) 组数据, \(\sum_{i=1}^{T}n\leq 10^6\) 。

思路

将子树按 \(dfs\) 序转化为区间,之后求区间内有多少个数字连续的段。我们可以使用树状数组,用一个 \(vis[\space]\) 来记录每个数字是否出现过,我们对区间从前往后遍历,对于每一个数字 \(i\) ,如果 \(i-1,i+1\) 都没有出现过,说明是新的一段,于是在这个位置 \(+1\) ;如果二者仅有一个出现过,说明段数没有变化;如果都出现过,说明有两个段被合并为了一个段,于是需要在这个位置 \(-1\)。这样查询区间 \([1,x]\) 的时候就是对前 \(x\) 个位置上的数求和即可。如果查询的左端点不是 \(1\) 那么我们要考虑去掉左侧不属于查询区间部分的影响,对于其中的每一个数字 \(i\) ,其会影响到 \(i-1,i+1\) 对应位置上的值,因为 \(i\) 是更早出现的,所以此时我们把那两个值 \(+1\) , 将 \(i\) 对应位置上的值置为 \(0\) ,然后对于查询区间 \([l,r]\) ,答案依然是前 \(r\) 个值的和。我们对所有询问按查询的左端点排序,依次查询即可,复杂度 \(O(nlogn)\) 。

代码

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
#define all(x) x.begin(),x.end()
//#define int LL
//#define lc p*2+1
//#define rc p*2+2
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#pragma warning(disable :4996)
const long double eps = 1e-15;
const LL MOD = 1000000007;
const LL mod = 998244353;
const int maxn = 200010; int T, N, cnt = 0;
vector<int>G[maxn];
int dfn[maxn], in[maxn], out[maxn], rnk = 0, A[maxn];
bool vis[maxn];
int dat[maxn], n, ans[maxn], val[maxn];
struct Query{
int l, r, id;
}Q[maxn]; bool cmp(const Query& a, const Query& b)
{
return a.l < b.l;
} void add(int i, int x)
{
while (i <= n)
{
dat[i] += x;
i += i & (-i);
}
} int sum(int i)
{
int ans = 0;
while (i)
{
ans += dat[i];
i -= i & (-i);
} return ans;
} void add_edge(int from, int to)
{
G[from].push_back(to);
G[to].push_back(from);
} void dfs(int v, int p)
{
in[v] = dfn[v] = ++rnk;
A[dfn[v]] = v;
val[dfn[v]] = 0;
for (int i = 0; i < G[v].size(); i++)
{
int to = G[v][i];
if (to == p)
continue;
dfs(to, v);
}
out[v] = rnk;
} void solve()
{
rnk = 0;
dfs(1, 0);
n = N;
for (int i = 1; i <= N; i++)
{
if (!vis[A[i] + 1] && !vis[A[i] - 1])
{
add(i, 1);
val[i]++;
}
else if (vis[A[i] + 1] && vis[A[i] - 1])
{
add(i, -1);
val[i]--;
}
vis[A[i]] = true;
} for (int i = 1; i <= N; i++)
Q[i] = Query({ in[i], out[i], i });
sort(Q + 1, Q + N + 1, cmp);
int nl = 1;
for (int i = 1; i <= N; i++)
{
int l = Q[i].l, r = Q[i].r;
while (nl < l)
{
if (A[nl] != N && dfn[A[nl] + 1] > nl)
{
add(dfn[A[nl] + 1], 1);
val[dfn[A[nl] + 1]]++;
}
if (A[nl] != 1 && dfn[A[nl] - 1] > nl)
{
add(dfn[A[nl] - 1], 1);
val[dfn[A[nl] - 1]]++;
}
add(nl, -val[nl]);
val[nl] = 0;
nl++;
}
ans[Q[i].id] = sum(r);
}
cout << "Case #" << cnt << ": ";
for (int i = 1; i <= N; i++)
cout << ans[i] << (i == N ? endl : ' ');
} int main()
{
IOS;
cin >> T;
while (T--)
{
memset(vis, false, sizeof(vis));
memset(dat, 0, sizeof(dat));
cnt++;
cin >> N;
int u, v;
for (int i = 1; i <= N; i++)
G[i].clear();
for (int i = 1; i < N; i++)
{
cin >> u >> v;
add_edge(u, v);
}
solve();
} return 0;
}

2019CCPC Final K. Russian Dolls on the Christmas Tree的更多相关文章

  1. POJ Big Christmas Tree(最短的基础)

    Big Christmas Tree 题目分析: 叫你构造一颗圣诞树,使得 (sum of weights of all descendant nodes) × (unit price of the ...

  2. POJ3013 Big Christmas Tree[转换 最短路]

    Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 23387   Accepted: 5 ...

  3. poj 3013 Big Christmas Tree (最短路径Dijsktra) -- 第一次用优先队列写Dijsktra

    http://poj.org/problem?id=3013 Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total S ...

  4. poj 3013 Big Christmas Tree Djistra

    Big Christmas Tree 题意:图中每个节点和边都有权值,图中找出一颗树,树根为1使得 Σ(树中的节点到树根的距离)*(以该节点为子树的所有节点的权值之和) 结果最小: 分析:直接求出每个 ...

  5. POJ 3013 Big Christmas Tree(最短Dijkstra+优先级队列优化,SPFA)

    POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA) ACM 题目地址:POJ 3013 题意:  圣诞树是由n个节点和e个边构成的,点编号1-n. ...

  6. poj 3013 Big Christmas Tree

    Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 20974   Accepted: 4 ...

  7. Big Christmas Tree(poj-3013)最短路

    Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 25823   Accepted: 5 ...

  8. 2019CCPC秦皇岛 K MUV LUV UNLIMITED(博弈)

    MUV LUV UNLIMITED Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  9. HDU - 5156 Harry and Christmas tree

    题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5156 题意 : 给一颗编号为1-n的以1为根的树, 已知有m个颜色的礼物分布在某些节点上(同一节点 ...

随机推荐

  1. RSS生成工具/服务推荐

    时至2022,关于碎片化阅读.信息焦虑的讨论仍在继续且似乎并没有形成广泛共识的解决办法.而研究生期间主要研究方向就是推荐系统且未来也大概率从事相关岗位的我,对以算法为中心的信息获取方式可以说是又爱又恨 ...

  2. Java枚举-通过值查找对应的枚举

    一.背景 Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等. 最近工作中,对接了很多其他的系统,发现对接的同一个系统 ...

  3. Typora + picgo + Chevereto 优雅地上传图片

    需求:由于经常使用typora写文章,但是配合picgo使用的sm.ms图床,github图床等,速度不稳定,因此我们想要利用自己的服务器搭建自己的图床,将自己文章的图片上传到自己的服务器中,优雅地写 ...

  4. .NET 诞生已20周年,您的 .NET 技能是否还停留在2010 年?

    20年来,我们见证了超过上千万.NET 开发员,当前有600万.NET 开发者正在使用.NET技术构建各类解决方案.今天,IT市场对.NET 开发人员的需求达到了前所未有的程度,特别是在中国,各大公司 ...

  5. go http 中间件

  6. Mysql8.0主从配置

    环境Centos7.6 ,mysql8.0 Mysql主从配置 1.1 配置环境: 本人在vm下做的实验,linux版本是centos的7.0版本,然后Mysql版本为此时较新的8.0.13版本.做最 ...

  7. JAVA多线程学习九-原子性操作类的应用

    当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可能i不等于3,而是等于2.因为A和B线程在更新变量i ...

  8. uniapp自定义顶部搜索框兼容微信小程序

    zhuanzai:  uniapp自定义顶部搜索框兼容微信小程序 自定义组件 navbarvue (胶囊底部高度 - 状态栏的高度) + (胶囊顶部高度 - 状态栏内的高度) = 导航栏的高度 < ...

  9. 解压命令tar zxvf中zxvf分别是什么意思

    x : 从 tar 包中把文件提取出来z : 表示 tar 包是被 gzip 压缩过的,所以解压时需要用 gunzip 解压v : 显示详细信息f xxx.tar.gz : 指定被处理的文件是 xxx ...

  10. LNMP架构——源码编译安装

    LNMP架构--源码编译安装 1.编译安装nginx服务 2.编译安装mysql服务 3.编译安装php解析环境 1.编译安装nginx服务: systemctl stop firewalld sys ...