【学术篇】SPOJ FTOUR2 点分治
淀粉质入门第一道 (现在个人认为spoj比bzoj要好_(:з」∠)_
关于点分治的话推荐去看一看漆子超的论文>>>这里这里<<<
之前一直试图入点分治坑, 但是因为种(bu)种(duan)原(tui)因(fei)也没有入...
结果经常碰到点分治的题目... 然后就各种弃疗...
不少点分治的题目有非常明显的特征... 通常是给一棵树, 然后问你满足xx条件的路径有多少条/是否存在/最大(小)权值之类的...
然后点分治的做法也不尽相同 大致能写出如下的伪代码(好吧还是用python高亮)
def solve(x): # 处理以x为根的子树
vis[x]=1 # 把x标记为操作过(视为删掉)
findroot(x) # 找到以x为根的子树的重心
calc(x) # 统计过x的路径的答案
for i in son[x]: # 对于每个儿子
solve(i) # 递归处理答案
然后刚入门第一道就不能算是很裸的点分治_(:з」∠)_
几乎抄了黄学长的代码, 在此表示感谢..
<题目の传送门>
hzwer题解の传送门
题目大意:
给一棵树, 有\(m\)个点上有一个标记, 边有边权, 可正可负.
询问路径上带标记的点不超过\(k\)个的路径的最大权值是多少.
首先朴素的思路就是暴力嘛... 复杂度\(O(n^2)\)的.. 可能能拿30~40(但这是spoj所以并没有什么部分分..)
我们要考虑复杂度更好的做法.. 首先根据上面我们说过的特征, 可以看出这题应该可以用点分治做...
因为后面是递归处理的, 我们只需要考虑如何统计合法的过根节点的路径的答案就行了..
我们需要处理出\(dep[y]\)和\(dis[y]\)两个数组, 分别表示\(y\)到当前的根节点(以下的根节点均指当前子树的根节点, 因为原来的根节点处理过就删掉了)的路径上的带标记节点个数和路径权值和. 这个可以通过一遍dfs\(O(n)\)完成...
然后我们考虑有哪些路径会对答案产生影响...
假如我们要处理\(x\)的\(i\)个子树, 那么前\(i-1\)个子树中的点可以与这个子树中的点确定一条路径.
我们再用一遍\(O(n)\)的dfs处理出\(mx[t]\)这个数组, 表示从前\(i-1\)棵子树中到根节点的经过\(t\)个带标记节点的路径的最大长度..
那我们就可以得到:
\]
但是这个dep[x]是会变的, 所以我们可以把儿子按照dep排序一波再做, 就可以顺着推过去了, 据说这样的复杂度是\(O(n)\)级别的..
然后排序的话总共也就只是\(O(nlogn)\)级别的东西, 配合着点分治的复杂度, 最后就是\(O(nlogn)\)咯..
代码:
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define depth first
#define id second
const int N=202020;
inline int gn(int a=0,char c=0,int f=1){
for(;(c<48||c>57)&&c!='-';c=getchar());if(c=='-')c=getchar(),f=-1;
for(;c>47&&c<58;c=getchar()) a=a*10+c-'0'; return a*f;
}
struct edge{
int to,next,data;
}e[N<<1]; int v[N],tot,n,m,k,rt,size,ans;
void buildedge(int x,int y,int z){
e[++tot].to=y; e[tot].next=v[x]; v[x]=tot; e[tot].data=z;
e[++tot].to=x; e[tot].next=v[y]; v[y]=tot; e[tot].data=z;
}
int q[N],fa[N],son[N],sz[N],mx[N],tmp[N],dep[N],d[N],depmx;
bool vis[N],a[N];
void findrt(int x,int fa){
sz[x]=1; son[x]=0;
for(int i=v[x];i;i=e[i].next)
if(!vis[e[i].to]&&e[i].to!=fa){
findrt(e[i].to,x);
son[x]=max(son[x],sz[e[i].to]);
sz[x]+=sz[e[i].to];
}
son[x]=max(son[x],size-sz[x]);
if(son[x]<son[rt]) rt=x;
}
void calcdis(int x,int fa){
depmx=max(depmx,dep[x]);
for(int i=v[x];i;i=e[i].next)
if(!vis[e[i].to]&&e[i].to!=fa){
dep[e[i].to]=dep[x]+a[e[i].to];
d[e[i].to]=d[x]+e[i].data;
calcdis(e[i].to,x);
}
}
void calcmax(int x,int fa){
tmp[dep[x]]=max(tmp[dep[x]],d[x]);
for(int i=v[x];i;i=e[i].next)
if(!vis[e[i].to]&&e[i].to!=fa)
calcmax(e[i].to,x);
}
vector<pair<int,int> > vec;
void solve(int x){
vis[x]=1; vec.clear(); if(a[x]) --k;
for(int i=v[x];i;i=e[i].next)
if(!vis[e[i].to]){
depmx=0;
dep[e[i].to]=a[e[i].to];
d[e[i].to]=e[i].data;
calcdis(e[i].to,x);
vec.push_back(make_pair(depmx,e[i].to));
}
sort(vec.begin(),vec.end());
for(int i=0;i<vec.size();++i){
calcmax(vec[i].id,x);
int now=0;
if(i!=0)
for(int j=vec[i].depth;j>=0;--j){
while(now+j<k&&now<vec[i-1].depth)
++now,mx[now]=max(mx[now],mx[now-1]);
if(now+j<=k) ans=max(ans,mx[now]+tmp[j]);
}
if(i!=vec.size()-1)
for(int j=0;j<=vec[i].depth;++j)
mx[j]=max(mx[j],tmp[j]),tmp[j]=0;
else
for(int j=0;j<=vec[i].depth;++j){
if(j<=k) ans=max(ans,max(tmp[j],mx[j]));
tmp[j]=mx[j]=0;
}
}
if(a[x]) ++k;
for(int i=v[x];i;i=e[i].next)
if(!vis[e[i].to]){
rt=0; size=sz[e[i].to];
findrt(e[i].to,x);
solve(rt);
}
}
int main(){
n=gn(),k=gn(),m=gn();
for(int i=1;i<=m;++i) a[gn()]=1;
for(int i=1;i<n;++i){
int x=gn(),y=gn(),z=gn();
buildedge(x,y,z);
}
size=son[0]=n; findrt(1,0);
solve(rt);
printf("%d",ans);
}
【学术篇】SPOJ FTOUR2 点分治的更多相关文章
- 【学术篇】CF833B TheBakery 分治dp+主席树
题目の传送门~ 题目大意: 将\(n\)个蛋糕分成恰好\(k\)份, 求每份中包含的蛋糕的种类数之和的最大值. 这题有两种做法. 第一种是线段树优化dp, 我还没有考虑. 另一种就是分治+主席树. 然 ...
- [spoj] FTOUR2 FREE TOUR II || 树分治
原题 给出一颗有n个点的树,其中有M个点是拥挤的,请选出一条最多包含k个拥挤的点的路径使得经过的权值和最大. 正常树分治,每次处理路径,更新答案. 计算每棵子树的deep(本题以经过拥挤节点个数作为d ...
- SPOJ - FTOUR2 (点分治+树状数组)
题目:https://vjudge.net/contest/307753#problem/I 题意:有一颗树,上面有白色黑色点,每个点上有一个权值,权值可以为负,现在我要求一条路径,权值和最大,这条路 ...
- 【学术篇】SPOJ GEN Text Generator AC自动机+矩阵快速幂
还有5天省选才开始点字符串这棵技能树是不是太晚了点... ~题目の传送门~ AC自动机不想讲了QAQ.其实很久以前是学过然后打过板子的, 但也仅限于打过板子了~ 之前莫名其妙学了一个指针版的但是好像不 ...
- 【学术篇】bzoj3262 陌上花开. cdq分治入门
花儿们已经很累了-- 无论是花形.颜色.还是气味, 都不是为了给人们摆出来欣赏的, 更不是为了当做出题的素材的, 她们并不想自己这些属性被没有生命的数字量化, 并不想和其它的花攀比, 并无意分出个三六 ...
- 【学术篇】SPOJ QTREE 树链剖分
发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧.. WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能 ...
- 【学术篇】SPOJ COT 树上主席树
这是学完主席树去写的第二道题_(:з」∠)_ 之前用树上莫队水过了COT2... 其实COT也可以用树上莫队水过去不过好像复杂度要带个log还是怎么样可能会被卡常数.. 那就orz主席吧.... 写了 ...
- 【学术篇】一些水的不行的dp
最近做了几道非常水非常水的dp...... 之后刷的一些水dp也会写在这里...... 此篇题目难度不递增!!! Emmmm....... 1.luogu1043数字游戏 以前看过这个题几遍,没做这个 ...
- SPOJ FTOUR2 - Free tour II
Description 有些黑点,问你选择不超过 \(k\) 个黑点的路径,路径权值最大是多少. Sol 点分治. 这是qzc的论文题,不过我感觉他的翻译好强啊...我还是选择了自己去看题目... 点 ...
随机推荐
- SpringMVC以及SSM整合
本人才疏学浅,如有错误欢迎批评!转载请注明出处:https://www.cnblogs.com/lee-yangyaozi/p/11226145.html SpringMVC概述 Spring Web ...
- js的width函数
参考: (1)https://blog.csdn.net/chen__jinfei/article/details/6520678 (2)https://developer.mozilla.org/e ...
- 如何设置和使用MacOS上的Microsoft Office套件
自30年前首次发布以来,Microsoft Office已成为全球最受欢迎的生产力套件之一.借助Word和Excel for Mac之类的程序,毫无疑问,MS Office套件在任何计算机上都是必须下 ...
- BD贴吧图片爬虫
#encoding:utf-8 import urllib import urllib.request from lxml import etree class Spider(object): def ...
- Docker 初识之路
一. 安装配置 1.安装依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 2.设置阿里云镜像源 sudo yu ...
- Vue学习笔记【16】——vue-resource 实现 get, post, jsonp请求
除了 vue-resource 之外,还可以使用 axios 的第三方包实现实现数据的请求 之前的学习中,如何发起数据请求?原生.jQuery,需要操作DOM 常见的数据请求类型? get post ...
- 芜湖市2018市队选拔Day2T1
好激动啊,Day2竟然AK了! Day2T1养宠物 Descriptionbadgers是可爱的动物,Smart想拥有一些.宠物店提供N个badgers,编号为1..N,Smart都很喜欢,所以他想拥 ...
- spring boot基于DRUID数据源密码加密及数据源监控实现
前言 随着需求和技术的日益革新,spring boot框架是越来越流行,她也越来越多地出现在我们的项目中,当然最主要的原因还是因为spring boot构建项目实在是太爽了,构建方便,开发简单,而且效 ...
- 排序算法(三)堆排序及有界堆排序Java实现及分析
1.堆排序基数排序适用于大小有界的东西,除了他之外,还有一种你可能遇到的其它专用排序算法:有界堆排序.如果你在处理非常大的数据集,你想要得到前 10 个或者前k个元素,其中k远小于n,它是很有用的. ...
- nodejs 内存泄漏
This looks OK at first glance. We could think that theThing get's overwritten with every invocation ...