题目大意

一棵 \(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. python网络爬虫-静态网页抓取(四)

    静态网页抓取 在网站设计中,纯HTML格式的网页通常被称之为静态网页,在网络爬虫中静态网页的数据比较容易抓取,因为说有的数据都呈现在网页的HTML代码中.相对而言使用Ajax动态加载的玩个的数据不一定 ...

  2. SQL语句 order by 升序和 降序查询

    原文 https://blog.csdn.net/u010649766/article/details/76180523?utm_medium=distribute.pc_relevant_t0.no ...

  3. Redis 源码简洁剖析 05 - ziplist 压缩列表

    ziplist 是什么 Redis 哪些数据结构使用了 ziplist? ziplist 特点 优点 缺点 ziplist 数据结构 ziplist 节点 pre_entry_length encod ...

  4. Spring学习七:ComponentScan注解

    今天主要从以下几个方面来介绍一下@ComponentScan注解: @ComponentScan注解是什么 @ComponentScan注解的详细使用 1.ComponentScan注解是什么 其实很 ...

  5. FidBugs的使用学习

    是什么? 静态代码分析器,它检查类或者JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题.Findbugs自带检测器,其中有60余种Bad practice,80余种Correctness, ...

  6. Xcode全系列下载地址

    Xcode全系列下载地址,不断更新dmg 格式 下载链接:http://pan.baidu.com/s/1mgyxLP2

  7. vue中的钩子函数

    什么是vue的钩子函数? Vue 实例在被创建时,会经过一系列的初始化过程,初始化过程中会运行一些函数,叫做生命周期钩子函数,通过运用钩子函数,用户在可以在Vue实例初始化的不同阶段添加自己的代码,以 ...

  8. 关于一些基础的dp——硬币的那些事(dp的基本引入)

    1.最少硬币问题大体题意: 有n种硬币,面值分别是v1,v2......vn,数量无限,输入一个非负整数s,选用硬币使其和为s,要求输出最少的硬币组合. 我们可以这样分析: 定义一个名为Min[s]的 ...

  9. Oracle用户创建、删除和授权等方法总结

    一.查看用户及权限 1.查询所有用户: 1.1.查看所有用户基本信息 select * from all_users; 1.2.查看所有用户相信信息 select * from dba_users; ...

  10. 基于PXIe接口的CoaXpress高速相机图像采集、回放

    PXIe简介 PCI eXtensions for Instrumentation or PXI is a computer-based hardware and software platform ...