传送门

这题卡常……而且目前还没有卡过去

首先以原树重心为根,向所有子树重心连边,可以建立一棵点分树

点分树有两个性质:

一个是树高只有log层

另一个是两点在点分树上的lca一定在原树上两点间的树上路径上

所以在原树上不断删点,并统计当前子树中的信息就好

至于如何统计,令 \(dp[i][j][k][l]\) 表示分治中心为 \(i\) ,到点 \(j\) ,第一条边颜色为 \(k\) ,最后一条边颜色为 \(j\) 的最大得分

转移挺好写的,询问时暴力枚举相关连边的颜色

留个坑,纯点分治还不会写呢

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define reg register int
#define fir first
#define sec second
#define make make_pair
#define pb push_back
#define min2(a, b) ((a)<(b)?(a):(b))
#define max2(a, b) ((a)>(b)?(a):(b))
//#define int long long char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
} int n, m, q;
int head[N], size;
struct edge{int to, next, val;}e[N*3];
inline void add(int s, int t, int w) {e[++size].to=t; e[size].val=w; e[size].next=head[s]; head[s]=size;} namespace force{
bool none[N];
int dfs(int u, int to, int fa, int now, int sum) {
//cout<<"dfs "<<u<<' '<<to<<' '<<fa<<' '<<now<<' '<<sum<<endl;
if (u==to) return sum;
int ans=0;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (v==fa || none[v]) continue;
ans=max(ans, dfs(v, to, u, e[i].val, sum+(now!=e[i].val)));
}
if (!ans) none[u]=1;
return ans;
}
void solve() {
for (int i=1,u,v,w; i<=m; ++i) {
u=read(); v=read(); w=read();
add(u, v, w); add(v, u, w);
}
q=read();
if (!q) exit(0);
for (int i=1,x,y; i<=q; ++i) {
x=read(); y=read();
memset(none, 0, sizeof(bool)*(n+5));
printf("%d\n", dfs(x, y, 0, 0, 0));
}
exit(0);
}
} namespace task1{
bool none[N];
int dfs(int u, int to, int fa, int now, int sum, int dis) {
//cout<<"dfs "<<u<<' '<<to<<' '<<fa<<' '<<now<<' '<<sum<<endl;
if (dis>60) {none[u]=1; return 0;}
if (u==to) return sum;
int ans=0;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (v==fa || none[v]) continue;
ans=max(ans, dfs(v, to, u, e[i].val, sum+(now!=e[i].val), dis+1));
}
if (!ans) none[u]=1;
return ans;
}
void solve() {
for (int i=1,u,v,w; i<=m; ++i) {
u=read(); v=read(); w=read();
add(u, v, w); add(v, u, w);
}
q=read();
if (!q) exit(0);
for (int i=1,x,y; i<=q; ++i) {
x=read(); y=read();
memset(none, 0, sizeof(bool)*(n+5));
printf("%d\n", dfs(x, y, 0, 0, 0, 0));
}
exit(0);
}
} namespace task{
int fa[N][25], dep[N], lg[N], rot, siz[N], msiz[N], sumsiz;
bool rm[N];
struct st{int i, j, k; st() {} st(int a, int b, int c):i(a),j(b),k(c){}};
inline bool operator == (st a, st b) {return a.i==b.i&&a.j==b.j&&a.k==b.k;}
inline bool operator < (st a, st b) {return a.k<b.k;}
struct pair_hash{inline size_t operator () (pair<int, int> p) const {return hash<int>()(p.fir*p.sec+p.fir);}};
unordered_map<pair<int, int>, vector<int>*, pair_hash> mp{5000, pair_hash()};
unordered_map<pair<int, int>, vector<st>*, pair_hash> dp{20000, pair_hash()};
unordered_map<pair<int, int>, int, pair_hash> tem{50, pair_hash()};
struct edge{int to, next;}e2[N<<1];
inline void add(int s, int t) {e2[++size].to=t; e2[size].next=head[s]; head[s]=size;}
vector<int> e[N];
void getrt(int u, int fa) {
//cout<<"getrt"<<u<<' '<<fa<<endl;
siz[u]=1; msiz[u]=0;
for (register auto v:e[u]) {
if (!rm[v] && v!=fa) {
getrt(v, u);
siz[u]+=siz[v];
msiz[u]=max(msiz[u], siz[v]);
}
}
//cout<<"sumsiz: "<<sumsiz<<' '<<sumsiz-siz[u]<<' '<<msiz[u]<<' '<<msiz[rot]<<' '<<rot<<endl;
msiz[u]=max(msiz[u], sumsiz-siz[u]);
if (msiz[u]<msiz[rot]) rot=u;
}
void info(int u, int fa) {
//cout<<"info "<<u<<' '<<fa<<endl;
for (register auto v:e[u]) {
if (v==fa || rm[v]) continue;
if (rot==u) {
if (dp.find(make(u, v))==dp.end()) dp[make(u, v)]=new vector<st>;
auto t1=mp[make(u, v)]; auto t2=dp[make(u, v)];
for (register auto it:*t1)
t2->pb(st(it, it, 1));
}
else {
if (dp.find(make(rot, v))==dp.end()) dp[make(rot, v)]=new vector<st>;
for (register auto it:*dp[make(rot, u)])
for (register auto t:*mp[make(u, v)])
tem[make(it.i, t)] = max(tem[make(it.i, t)], it.k+(it.j!=t));
register auto t1=dp[make(rot, v)];
for (register auto it:tem) t1->pb(st(it.fir.fir, it.fir.sec, it.sec));
//assert(tem.size()<=9);
tem.clear();
}
info(v, u);
//cout<<"size: "<<dp.size()<<endl;
}
}
void build(int u) {
//cout<<"build "<<u<<endl;
rm[u]=1;
info(u, 0);
for (register auto v:e[u]) {
rot=0;
if (!rm[v]) {
sumsiz=siz[v];
getrt(v, u);
add(u, rot), add(rot, u);
//info(rot, u, t);
build(rot);
}
}
}
void dfs(int u, int pa) {
//cout<<"dfs "<<u<<' '<<pa<<endl;
for (reg i=1; i<25; ++i)
if (dep[u]>=(1<<i)) fa[u][i] = fa[fa[u][i-1]][i-1];
else break;
for (reg i=head[u],v; ~i; i=e2[i].next) {
v = e2[i].to;
if (v!=pa) dep[v]=dep[u]+1, fa[v][0]=u, dfs(v, u);
}
}
int lca(int a, int b) {
if (dep[a]<dep[b]) swap(a, b);
while (dep[a]>dep[b]) a=fa[a][lg[dep[a]-dep[b]]-1];
if (a==b) return a;
for (reg i=lg[dep[a]]-1; ~i; --i)
if (fa[a][i]!=fa[b][i])
a=fa[a][i], b=fa[b][i];
return fa[a][0];
}
void solve() {
for (reg i=1; i<=n; ++i) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
pair<int, int> t1, t2;
for (reg i=1,u,v,w; i<=m; ++i) {
u=read(); v=read(); w=read();
e[u].pb(v); e[v].pb(u);
t1=make(u, v), t2=make(v, u);
if (mp.find(t1)==mp.end()) mp[t1]=new vector<int>;
mp[t1]->pb(w);
if (mp.find(t2)==mp.end()) mp[t2]=new vector<int>;
mp[t2]->pb(w);
}
for (reg i=1,siz; i<=n; ++i) {
sort(e[i].begin(), e[i].end());
siz=unique(e[i].begin(), e[i].end())-e[i].begin();
e[i].resize(siz);
}
for (register auto it:mp) {
sort(it.sec->begin(), it.sec->end());
int siz=unique(it.sec->begin(), it.sec->end())-it.sec->begin();
it.sec->resize(min2(siz, 3));
} msiz[0]=sumsiz=n;
getrt(1, 0);
int root=rot;
//cout<<"root: "<<root<<endl;
build(rot);
dep[root]=1;
dfs(root, 0); //for (auto it:dp) cout<<it.fir.i<<' '<<it.fir.j<<' '<<it.fir.k<<' '<<it.fir.h<<' '<<it.sec<<endl; q=read(); if (!q) exit(0);
for (reg i=1,x,y,t,ans; i<=q; ++i) {
x=read(); y=read();
if (x==y) {puts("0"); continue;}
t=lca(x, y); ans=0;
//cout<<"lca: "<<x<<' '<<y<<' '<<t<<endl;
if (t==x || t==y) {
//puts("pos1");
if (t!=x) swap(x, y);
for (register auto it:*dp[make(t, y)]) ans=max(ans, it.k);
printf("%d\n", ans);
continue;
}
for (register auto i:*dp[make(t, x)])
for (register auto j:*dp[make(t, y)])
ans = max(ans, i.k+j.k-(i.i==j.i));
printf("%d\n", ans);
}
//cout<<"size: "<<dp.size()<<endl;
exit(0);
}
} signed main()
{
memset(head, -1, sizeof(head));
n=read(); m=read();
//if (n<100000) force::solve();
//else task1::solve();
task::solve(); return 0;
}

题解 c(留坑)的更多相关文章

  1. Codeforces Round #364 (Div. 1)(vp) 没什么题解就留坑待填

    我就做了前两题,第一题第一次vp就把我搞自闭跑路了,第二题第二次又把我搞自闭了 A. As Fast As Possible 细节题 #include<cstdio> #include&l ...

  2. [kuangbin带你飞]专题十一 网络流个人题解(L题留坑)

    A - ACM Computer Factory 题目描述:某个工厂可以利用P个部件做一台电脑,有N个加工用的机器,但是每一个机器需要特定的部分才能加工,给你P与N,然后是N行描述机器的最大同时加工数 ...

  3. 题解 queen(留坑)

    传送门 博客园突然打不开了,奇奇怪怪的-- 少写个等号没看出来 nm写反了没看出来 考完5min全拍出来了 手残属性加持 不对拍等于爆零 yysy,我连卢卡斯定理的存在都忘了-- 发现要让一大堆皇后能 ...

  4. 2.18比赛(T2,T3留坑)

    2.18比赛(T2,T3留坑) pdf版题面 pdf版题解 超越一切(ak) [题目描述] 夏洛可得到一个(h+1)×(w+1)的巧克力,这意味着她横着最多可 以切 h 刀,竖着最多可以切 w 刀 她 ...

  5. CPU虚拟化技术(留坑)

    留坑~~~ 不知道这个是这么实现的 CPU虚拟化技术就是单CPU模拟多CPU并行,允许一个平台同时运行多个操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率.虚 ...

  6. 【留坑】uva12299

    这么sb的题本来想练练手记过就是过不了 拍半天也没问题 留坑 哪天有空了去linux下面试试 #include<cstdio> #include<cstring> #inclu ...

  7. 【问题解决方案】Git bash进入多层子目录问题(通配符问题留坑)

    cd进入指定路径下:cd 斜杠 斜杠 方法一: 1- 撇丿,不是"那",盘符前面要加上 / (d盘前面也加,不加也行) 2- 路径名不区分大小写 3- 不用空格 4- 如果目录名中 ...

  8. 题解 Six(留坑)

    传送门 考场上搞了个三进制状压,结果正确性假了-- 有想到从约数下手,但觉得就光预处理约数复杂度就爆炸就没往这边想-- 首先是关于约数个数的证明,再一次感谢战神: 因为 \(n = \prod p_i ...

  9. 培训补坑(day7:线段树的区间修改与运用)(day6是测试,测试题解以后补坑QAQ)

    补坑咯~ 今天围绕的是一个神奇的数据结构:线段树.(感觉叫做区间树也挺科学的.) 线段树,顾名思义就是用来查找一段区间内的最大值,最小值,区间和等等元素. 那么这个线段树有什么优势呢? 比如我们要多次 ...

随机推荐

  1. mongodb,redis,mysql的区别和具体应用场景(转)

    一.MySQL 关系型数据库. 在不同的引擎上有不同 的存储方式. 查询语句是使用传统的sql语句,拥有较为成熟的体系,成熟度很高. 开源数据库的份额在不断增加,mysql的份额页在持续增长. 缺点就 ...

  2. ctf杂项之easy_nbt

    下载附件查看 除了几个文件之外,没有思路 搜索nbt可知,可以使用nbtexplorer工具 果断下载,然后打开题目下载的目录 crrl+f搜索flag 猜测kflag{Do_u_kN0w_nbt?} ...

  3. 【BZOJ 4771】七彩树

    一直TLE的原因竟然是数组开太大了导致\(memset\)清空耗时超限,亏我还调了1天啊(T^T) 题目大意 给定一颗树,每个节点都有一个颜色,要求多次询问某个节点\(x\)的子树中深度不超过\(d\ ...

  4. python05篇 json和函数

    一.json json就是一个字符串,只不过是所有语言能解析这个字符串.1.1 把python的数据类型转为json import json d = {'name': 'xiaohei', 'cars ...

  5. WSL2:Windows 亲生的 Linux 子系统

    作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...

  6. facade层,service 层,domain层,dao 层设计

    转自http://fei-6666.iteye.com/blog/446247,记录下来 一,Service->DAO,只能在Service中注入DAO. 二,DAO只能操作但表数据,跨表操作放 ...

  7. 转载:使用jquery刷新当前页面以及其他js知识积累

    转载:https://www.cnblogs.com/heguihui/p/10505949.html 如何使用jquery刷新当前页面 下面介绍全页面刷新方法:有时候可能会用到 window.loc ...

  8. PAT乙级:1090危险品装箱(25分)

    PAT乙级:1090危险品装箱(25分) 题干 集装箱运输货物时,我们必须特别小心,不能把不相容的货物装在一只箱子里.比如氧化剂绝对不能跟易燃液体同箱,否则很容易造成爆炸. 本题给定一张不相容物品的清 ...

  9. SpringBoot+Redis 实现消息订阅发布

    什么是 Redis Redis 是一个开源的使用 ANSI C语言编写的内存数据库,它以 key-value 键值对的形式存储数据,高性能,读取速度快,也提供了持久化存储机制. Redis 通常在项目 ...

  10. K8S系列第四篇(Dockerfile)

    DokcerFile 镜像定制 更多精彩内容请关注微信公众号:新猿技术生态圈 定制docker镜像的方式有两种: 手动修改容器内容,导出新的镜像. 基于dockerfile自行编写指令,基于指令流程创 ...