以后传数组绝对用指针...

考虑点分治

在点分的时候,把相同的颜色的在一起合并

之后,把不同颜色依次合并

我们可以用单调队列做到单次合并$O(n + m)$

如果我们按照深度大小来合并,那么由于每次都是把大的往小的去合并

因此,合并$n$的序列最多需要$2n$的势能

因此,最终我们就能达到$O(n \log n)$的统计复杂度

然而还有排序,所以实际复杂度$O(n \log^2 n)$,排序常数很小,自然能过

#include <set>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
namespace remoon {
#define re register
#define de double
#define le long double
#define ri register int
#define ll long long
#define sh short
#define pii pair<int, int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define tpr template <typename ra>
#define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++)
#define drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --)
#define gc getchar
inline int read() {
int p = , w = ; char c = gc();
while(c > '' || c < '') { if(c == '-') w = -; c = gc(); }
while(c >= '' && c <= '') p = p * + c - '', c = gc(); return p * w;
}
int wr[], rw;
#define pc(iw) putchar(iw)
tpr inline void write(ra o, char c = '\n') {
if(!o) pc('');
if(o < ) o = -o, pc('-');
while(o) wr[++ rw] = o % , o /= ;
while(rw) pc(wr[rw --] + '');
pc(c);
}
tpr inline void cmin(ra &a, ra b) { if(a > b) a = b; }
tpr inline void cmax(ra &a, ra b) { if(a < b) a = b; }
tpr inline bool ckmin(ra &a, ra b) { return (a > b) ? a = b, : ; }
tpr inline bool ckmax(ra &a, ra b) { return (a < b) ? a = b, : ; }
}
using namespace std;
using namespace remoon; #define sid 400050
#define inf 1e9 int n, m, l, r, rt, asz, cnp, ans = -2e9;
int over[sid], son[sid], sz[sid], dep[sid], col[sid];
int cap[sid], nxt[sid], node[sid], cv[sid]; inline void addedge(int u, int v, int c) {
nxt[++ cnp] = cap[u]; cap[u] = cnp;
node[cnp] = v; col[cnp] = c;
} struct Ans {
int f[sid], end;
} nowc, prec, now; inline void init(Ans &a) {
rep(i, , a.end) a.f[i] = -inf;
a.end = ;
} inline void upd(Ans &a, Ans &b) {
int len = max(a.end, b.end); a.end = len;
rep(i, , len) {
cmax(a.f[i], b.f[i]);
if(l <= i && i <= r) cmax(ans, a.f[i]);
}
} int q[sid];
inline void qry(Ans &a, Ans &b, int opt = ) {
if(l == && r == n - ) {
int mx1 = -inf, mx2 = -inf;
rep(i, , a.end) cmax(mx1, a.f[i]);
rep(j, , b.end) cmax(mx2, b.f[j]);
cmax(ans, mx1 + mx2 - opt);
}
else {
int fr = , to = ;
drep(i, min(r, b.end), l) {
while(fr <= to && b.f[i] >= b.f[q[to]]) to --;
q[++ to] = i;
}
rep(i, , a.end) {
if(l - i >= ) {
while(fr <= to && b.f[l - i] >= b.f[q[to]]) to --;
q[++ to] = l - i;
}
while(fr <= to && q[fr] > r - i) fr ++;
if(fr <= to) cmax(ans, a.f[i] + b.f[q[fr]] - opt);
}
}
} int vis[sid], tim;
vector <pii> all, c[sid]; #define cur node[i]
inline void grt(int o, int fa) {
sz[o] = ; son[o] = ;
for(int i = cap[o]; i; i = nxt[i])
if(!over[cur] && cur != fa){
grt(cur, o); sz[o] += sz[cur];
cmax(son[o], sz[cur]);
}
cmax(son[o], asz - sz[o]);
if(son[o] < son[rt]) rt = o;
} inline int gh(int o, int fa) {
int tmp = dep[o];
for(ri i = cap[o]; i; i = nxt[i])
if(cur != fa && !over[cur]) {
dep[cur] = dep[o] + ;
cmax(tmp, gh(cur, o));
}
return tmp;
} inline void gt(int o, int fa, int val, int lst) {
sz[o] = ;
for(int i = cap[o]; i; i = nxt[i])
if(!over[cur] && cur != fa) {
int C = col[i];
int nxt = (C == lst) ? : cv[C];
gt(cur, o, val + nxt, C);
sz[o] += sz[cur];
}
cmax(now.end, dep[o]);
cmax(now.f[dep[o]], val);
} inline void solve(int o) { over[o] = ; ++ tim;
for(int i = cap[o]; i; i = nxt[i])
if(!over[cur]) {
int C = col[i];
if(vis[C] != tim) c[C].clear();
vis[C] = tim; dep[cur] = ;
c[C].pb(mp(gh(cur, o), cur));
}
++ tim;
all.clear();
for(int i = cap[o]; i; i = nxt[i])
if(!over[cur]) {
int C = col[i];
if(vis[C] != tim) {
vis[C] = tim;
sort(c[C].begin(), c[C].end());
int len = c[C][c[C].size() - ].fi;
all.pb(mp(len, C));
}
}
sort(all.begin(), all.end()); init(prec);
for(auto x : all) {
int C = x.se; init(nowc);
for(auto y : c[C]) {
init(now); gt(y.se, o, cv[C], C);
qry(now, nowc, cv[C]); upd(nowc, now);
}
qry(prec, nowc); upd(prec, nowc);
} for(int i = cap[o]; i; i = nxt[i])
if(!over[cur]) {
asz = sz[cur]; rt = ;
grt(cur, o); solve(rt);
}
} int main() {
n = read(); m = read();
l = read(); r = read();
rep(i, , m) cv[i] = read();
rep(i, , n) {
int u = read(), v = read(), w = read();
addedge(u, v, w); addedge(v, u, w);
}
rep(i, , n) now.f[i] = -inf;
rep(i, , n) prec.f[i] = -inf;
rep(i, , n) nowc.f[i] = -inf;
asz = n; son[] = n;
grt(, ); solve(rt);
write(ans);
return ;
}

luoguP3714 [BJOI2017]树的难题 点分治的更多相关文章

  1. [BJOI2017]树的难题 点分治 线段树

    题面 [BJOI2017]树的难题 题解 考虑点分治. 对于每个点,将所有边按照颜色排序. 那么只需要考虑如何合并2条链. 有2种情况. 合并路径的接口处2条路径颜色不同 合并路径的接口处2条路径颜色 ...

  2. [BJOI2017]树的难题 点分治,线段树合并

    [BJOI2017]树的难题 LG传送门 点分治+线段树合并. 我不会写单调队列,所以就写了好写的线段树. 考虑对于每一个分治中心,把出边按颜色排序,这样就能把颜色相同的子树放在一起处理.用一棵动态开 ...

  3. BZOJ4860 BJOI2017 树的难题 点分治、线段树合并

    传送门 只会线段树……关于单调队列的解法可以去看“重建计划”一题. 看到路径长度$\in [L,R]$考虑点分治.可以知道,在当前分治中心向其他点的路径中,始边(也就是分治中心到对应子树的根的那一条边 ...

  4. P3714 [BJOI2017]树的难题 点分治+线段树合并

    题目描述 题目传送门 分析 路径问题考虑点分治 对于一个分治中心,我们可以很容易地得到从它开始的一条路径的价值和长度 问题就是如何将不同的路径合并 很显然,对于同一个子树中的所有路径,它们起始的颜色是 ...

  5. 洛谷 P3714 - [BJOI2017]树的难题(点分治)

    洛谷题面传送门 咦?鸽子 tzc 竟然来补题解了?incredible( 首先看到这样类似于路径统计的问题我们可以非常自然地想到点分治.每次我们找出每个连通块的重心 \(x\) 然后以 \(x\) 为 ...

  6. 并不对劲的loj2179:p3714:[BJOI2017]树的难题

    题目大意 有一棵树,\(n\)(\(n\leq2*10^5\))个点,每条边\(i\)有颜色\(w_i\),共有\(m\)(\(m\leq n\))种颜色,第\(i\)种颜色的权值是\(c_i\)(\ ...

  7. [BJOI2017]树的难题

    题目描述 给你一棵 n 个点的无根树. 树上的每条边具有颜色.一共有 m 种颜色,编号为 1 到 m.第 i 种颜色的权值为 ci. 对于一条树上的简单路径,路径上经过的所有边按顺序组成一个颜色序列, ...

  8. 【BZOJ4016】[FJOI2014]最短路径树问题(点分治,最短路)

    [BZOJ4016][FJOI2014]最短路径树问题(点分治,最短路) 题面 BZOJ 洛谷 题解 首先把最短路径树给构建出来,然后直接点分治就行了. 这个东西似乎也可以长链剖分,然而没有必要. # ...

  9. BZOJ4860 Beijing2017树的难题(点分治+单调队列)

    考虑点分治.对子树按照根部颜色排序,每次处理一种颜色的子树,对同色和不同色两种情况分别做一遍即可,单调队列优化.但是注意到这里每次使用单调队列的复杂度是O(之前的子树最大深度+该子树深度),一不小心就 ...

随机推荐

  1. Vue笔记之模板语法

    插值 比较常用的就是插值,插值就是{{ foobar }}用两个大括号包起来的一个变量,显示的时候会将双大括号标签替换为这个变量的值. 基本的用法就是: <p>{{ message }}& ...

  2. struts的标签

    <%@ taglib uri="/struts-tags" prefix="s"%> <%@ taglib uri="/WEB-IN ...

  3. 24 - 面向对象基础-多继承-super-mro-Mixin

    目录 1 类的继承 2 不同版本的类 3 基本概念 4 特殊属性和方法 5 继承中的访问控制 6 方法的重写(override) 6.1 super 6.2 继承中的初始化 7 多继承 7.1 多继承 ...

  4. nginx之日志设置详解

    nginx的日志设置 access_log access_log是服务器记录了哪些用户,哪些页面以及用户浏览器.ip和其他的访问信息:是一种非常详细的记录信息:如果我们不关心谁访问了我们,可以关闭: ...

  5. Linux下用到数据库sqlite3

    最近在Linux下用到数据库sqlite3,于是开始了该方面的学习. 0. 引言 我们这篇文章主要讲述了如何在C/C++语言中调用 sqlite 的函数接口来实现对数据库的管理, 包括创建数据库.创建 ...

  6. 516.Longest Palindromic subsequence---dp

    题目链接:https://leetcode.com/problems/longest-palindromic-subsequence/description/ 题目大意:找出最长回文子序列(不连续), ...

  7. Swift中的指针类型

    Swift编程语言为了能与Objective-C与C语言兼容,而引入了指针类型.尽管官方不建议频繁使用指针类型,但很多时候,使用指针能完成更多.更灵活的任务.比如,我们要实现一个交换两个整数值的函数的 ...

  8. Class.this 和 this 的有什么不同

    转载:http://www.cnblogs.com/liwei45212/archive/2013/04/17/3026364.html 在阅读Java代码的時候 我们时会看到Class.this的使 ...

  9. NLP基础 成分句法分析和依存句法分析

    正则匹配: .除换行符所有的 ?表示0次或者1次 *表示0次或者n次 a(bc)+表示bc至少出现1次 ^x.*g$表示字符串以x开头,g结束 |或者 http://regexr.com/ 依存句法分 ...

  10. C# 随笔 【ToList().Foreach()和Foreach()】

    1. 最近在做一个Socket通讯的例子,但是如果使用UTF-8编码传输中文的话取和的会不一样.早上做了测试 . string str = "a我..";看代码中间是一个英文,一个 ...