[传送门]

题目即求所有的三元组,相对大小关系同 $p_1,p_2,p_3$。

题解说都很清楚,这里写一下过程整理一下思路。

如果我们枚举中间这个元素,那么就是统计子树内外有多少个大于这个数和小于这个数的个数。

假设$a_1$,$a_3$的$LCA$不是$a_2$,那么就是一个在$a_2$子树内一个在子树外。

设$S_u$, $B_u$分别为$u$子树内小于$u$和大于$u$的节点个数,$S_t$, $B_t$分别为整棵树小于$u$和大于$u$的节点个数。

当$p_2 = 1$时,对答案的贡献为$B_u \times (B_t - B_u)$

当$p_2 = 2$时,对答案的贡献为$B_u \times (S_t - S_u) + S_u \times (B_t - B_u)$

当$p_2 = 1$时,对答案的贡献为$S_u \times (S_t - S_u)$

当$a_1$和$a_3$的$LCA$是$a_2$时,枚举$u$的子节点。

设$S_v$为$u$的子节点$v$的子树中,小于$u$的节点个数,$B_v$为$u$的子节点$v$的子树中,大于$u$的节点个数。

当$p_2 = 1$时,对答案的贡献为$B_v \times (B_u - B_v)$

当$p_2 = 2$时,对答案的贡献为$S_v \times (B_u - B_v) + B_v \times (S_u - S_v)$

当$p_2 = 1$时,对答案的贡献为$S_v \times (S_u - S_v)$

这部分的贡献会被算两次,所以最后得除以二。

查子树内都多少节点大于/小于该节点的,题解用了dfs序+树状数组,但是对于第二部分求答案很麻烦。所以我用了线段树合并,不过会卡常,那么只求一遍小于的,再用子树的size减去这个值就得到大于的。

#include <bits/stdc++.h>
#define pii pair<int, int>
#define ll long long
using namespace std; namespace IO {
const int MAXSIZE = << ;
char buf[MAXSIZE], *p1, *p2;
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin), p1 == p2) ? EOF : *p1++)
template<class T>
inline void read(T &x) {
x = ; T f = ; char c = gc();
while (!isdigit(c)) { if (c == '-') f = -; c = gc(); }
while (isdigit(c)) x = x * + (c ^ ), c = gc();
x *= f;
}
char pbuf[ << ], *pp = pbuf;
inline void push(const char &c) {
if (pp - pbuf == << ) fwrite(pbuf, , << , stdout), pp = pbuf;
*pp++ = c;
}
inline void write(int x) {
static int sta[];
int top = ;
do {
sta[top++] = x % , x /= ;
} while (x);
while (top) push(sta[--top] + '');
}
} using namespace IO; const int N = 1e5 + ; int root[N], p[], n, sz[N];
vector<int> G[N]; struct Seg {
struct Tree {
int lp, rp, sum;
} tree[N * ];
int tol;
inline void clear() {
tol = ;
memset(tree, , sizeof(tree));
}
inline void pushup(int p) {
tree[p].sum = tree[tree[p].lp].sum + tree[tree[p].rp].sum;
}
void update(int &p, int l, int r, int pos) {
if (!p) p = ++tol;
if (l == r) {
tree[p].sum++;
return;
}
int mid = l + r >> ;
if (pos <= mid) update(tree[p].lp, l, mid, pos);
else update(tree[p].rp, mid + , r, pos);
pushup(p);
}
int merge(int p, int q, int l, int r) {
if (!p || !q) return p | q;
int u = ++tol;
int mid = l + r >> ;
tree[u].lp = merge(tree[p].lp, tree[q].lp, l, mid);
tree[u].rp = merge(tree[p].rp, tree[q].rp, mid + , r);
pushup(u);
return u;
}
int query(int p, int l, int r, int x, int y) {
if (x > y) return ;
if (!p) return ;
if (x <= l && y >= r) return tree[p].sum;
int mid = l + r >> ;
int ans = ;
if (x <= mid) ans += query(tree[p].lp, l, mid, x, y);
if (y > mid) ans += query(tree[p].rp, mid + , r, x, y);
return ans;
}
} seg; ll ans; inline void init() {
ans = ;
seg.clear();
for (int i = ; i <= n; i++) G[i].clear(), root[i] = ;
} void dfs(int u, int fa) {
seg.update(root[u], , n, u);
vector<pii> vec;
int su = , bu = ;
int st = u - , bt = n - u;
sz[u] = ;
for (auto v: G[u]) {
if (v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
int sv = seg.query(root[v], , n, , u - ), bv = sz[v] - sv;
su += sv, bu += bv;
vec.push_back(pii(sv, bv));
root[u] = seg.merge(root[u], root[v], , n);
}
if (p[] == )
ans += 1LL * bu * (bt - bu);
else if (p[] == )
ans += 1LL * bu * (st - su) + 1LL * su * (bt - bu);
else
ans += 1LL * su * (st - su);
ll res = ;
for (auto pp: vec) {
if (p[] == )
res += 1LL * pp.second * (bu - pp.second);
else if (p[] == )
res += 1LL * pp.first * (bu - pp.second) + 1LL * pp.second * (su - pp.first);
else
res += 1LL * pp.first * (su - pp.first);
}
ans += res / ;
} int main() {
// freopen("in.txt", "r", stdin);
int T;
read(T);
while (T--) {
read(n);
init();
for (int i = ; i < ; i++) read(p[i]);
for (int i = ; i < n; i++) {
int u, v;
read(u), read(v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(, );
printf("%lld\n", ans);
}
return ;
}

Codechef August Challenge 2019 Chef and Gordon Ramsay的更多相关文章

  1. Codechef August Challenge 2019 Division 2

    Preface 老年菜鸡终于开始打CC了,由于他太弱了所以只能打Div2 因为台风的原因challenge并没有写,所以水了个Rank7 A Football SB模拟题不解释 #include< ...

  2. Codechef August Challenge 2018 : Chef at the River

    传送门 (要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来 结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解. 首先这个数量肯定是下界,更少的话连第一次都 ...

  3. 【CodeChef】August Challenge 2019 Div2 解题报告

    点此进入比赛 \(T1\):Football(点此看题面) 大致题意: 求\(max(20a_i-10b_i,0)\). 送分题不解释. #include<bits/stdc++.h> # ...

  4. Codechef April Challenge 2019 游记

    Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...

  5. CF&&CC百套计划2 CodeChef December Challenge 2017 Chef And Easy Xor Queries

    https://www.codechef.com/DEC17/problems/CHEFEXQ 题意: 位置i的数改为k 询问区间[1,i]内有多少个前缀的异或和为k 分块 sum[i][j] 表示第 ...

  6. CF&&CC百套计划2 CodeChef December Challenge 2017 Chef and Hamming Distance of arrays

    https://www.codechef.com/DEC17/problems/CHEFHAM #include<cstdio> #include<cstring> #incl ...

  7. CF&&CC百套计划2 CodeChef December Challenge 2017 Chef And his Cake

    https://www.codechef.com/DEC17/problems/GIT01 #include<cstdio> #include<algorithm> using ...

  8. CodeChef April Challenge 2019题解

    传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...

  9. Codechef October Challenge 2019 Division 1

    Preface 这次CC难度较上两场升高了许多,后面两题都只能借着曲明姐姐和jz姐姐的仙气来做 值得一提的是原来的F大概需要大力分类讨论,结果我写了一大半题目就因为原题被ban了233 最后勉强涨了近 ...

随机推荐

  1. 【转帖】nmap命令总结

    nmap命令总结 https://www.cnblogs.com/chenqionghe/p/10657722.html 一.nmap是什么 nmap是一款网络扫描和主机检测的非常有用的工具,不局限于 ...

  2. Lua table concat

    [1]table concat 简介 使用方式: table.concat(table, sep, start, end) 作用简介: concat是concatenate(连锁.连接)的缩写. ta ...

  3. PowerBuilder学习笔记之14用户自定义对象

    教程链接:https://wenku.baidu.com/view/9730d1c7aa00b52acec7ca05.html?re=view&rec_flag=default&sxt ...

  4. AD常用术语

    SMD : Surface Mounted Devices 表面贴装器件 PAD 焊盘

  5. Java链表操作代码

    /** * */ package com.cherish.SwordRefersToOffer; /** * @author acer * */ public class test_22链表中倒数第k ...

  6. Win 10下安装 Redis

    目录 写在前面 一.安装环境 二.下载windows版本的Redis 三.安装Redis 四.安装服务 五.启动服务 六.测试Redis 七.常用的Redis服务. 写在前面 Redis 是一个开源使 ...

  7. intel AVX指令集

    听说这 AVX 很牛,,支持Win7,大幅提高游戏浮点运算性能warning C4752: 发现 Intel(R) 高级矢量扩展:请考虑使用 /arch:AVX

  8. 分布式系统根基:物理时钟和Lamport逻辑时钟

    分布式系统解决了传统单体架构的单点问题和性能容量问题,另一方面也带来了很多的问题,其中一个问题就是多节点的时间同步问题:不同机器上的物理时钟难以同步,导致无法区分在分布式系统中多个节点的事件时序.19 ...

  9. display:grid

    使用grid布局 参考资料http://www.ruanyifeng.com/blog/2019/03/grid-layout-tutorial.html flex布局还没完全用利索,但这个grid布 ...

  10. Ingress使用示例

    Ingress概念介绍 service只能做四层代理 无法做七层代理(如https服务)      lvs只能根据第四层的数据进行转发 无法对七层协议数据进行调度 Ingress Controller ...