点分治

  点分治的例题2(本题代码结果为TLE……)

  强烈谴责卡时限QAQ,T了无数次啊无数次……

  不过在N次的静态查错中倒是加深了对点分治的理解……也算因祸得福吧(自我安慰一下)

TLE后的改进:每棵子树在重算f数组的时候,不要完全清空,而是清到最深深度即可。——>WA

 //SPOJ 1825
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
using namespace std;
inline void read(int &v){
v=; int sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
v*=sign;
}
/******************tamplate*********************/
const int N=,INF=1e8;
int n,m,k,root=,h[N],s[N],g[N],f[N],size,d[N];
bool vis[N],black[N];
int to[N],head[N],next[N],len[N],tot=;
inline void ins(int x,int y,int l){
to[++tot]=y; next[tot]=head[x]; head[x]=tot; len[tot]=l;
to[++tot]=x; next[tot]=head[y]; head[y]=tot; len[tot]=l;
} inline void getroot(int x,int fa){
s[x]=;h[x]=;
for(int i=head[x];i;i=next[i])
if (to[i]!=fa && !vis[to[i]]){
getroot(to[i],x);
s[x]+=s[to[i]];
//h[x]=max(h[x],s[to[i]]);
if (s[to[i]]>h[x]) h[x]=s[to[i]];
}
h[x]=max(h[x],size-s[x]);
if (h[x]<h[root]) root=x;
} inline void getdep(int x,int fa){
int res=;
for(int i=head[x];i;i=next[i]){
if (to[i]!=fa && !vis[to[i]]){
d[to[i]]=d[x]+black[to[i]];
getdep(to[i],x);
res=max(res,d[to[i]]);
}
}
d[x]+=res;
}
inline void getg(int x,int fa,int leng,int c){
g[c]=max(g[c],leng);
for(int i=head[x];i;i=next[i])
if (to[i]!=fa && !vis[to[i]]) getg(to[i],x,leng+len[i],c+black[to[i]]);
}
struct node{int deep,to,len;}st[N];
inline bool cmp(const node &a,const node &b) {return a.deep<b.deep;}
int ans=,cnt; void getans(int x){
vis[x]=;
for(int i=head[x];i;i=next[i])
getdep(to[i],x);
cnt=;
F(i,,n) f[i]=;
for(int i=head[x];i;i=next[i]){
if (!vis[to[i]]){
d[to[i]]=black[to[i]];
getdep(to[i],x);
st[cnt++]=(node){d[to[i]],to[i],len[i]};
}
}
sort(st,st+cnt,cmp);
rep(i,cnt){
int y=st[i].to;
F(j,,d[y]) g[j]=-INF;
getg(y,x,st[i].len,black[y]);
if (i>){
int end=min(k-black[x],d[y]);
F(j,,end){
int p=min(d[st[i-].to],k-j-black[x]);
if (f[p]==-INF) break;
if (g[j]!=-INF) ans=max(ans,g[j]+f[p]);
}
}
F(j,,d[y]){
f[j]=max(f[j],g[j]);
if (j) f[j]=max(f[j],f[j-]);
if (j+black[x]<=k) ans=max(ans,f[j]);
}
} for(int i=head[x];i;i=next[i])
if (!vis[to[i]]){
root=; size=s[to[i]];
getroot(to[i],x);
getans(root);
}
} int main(){
// freopen("1825.in","r",stdin);
read(n); read(k); read(m);
int x,y,l;
F(i,,m){ read(x); black[x]|=;}
F(i,,n){
read(x); read(y); read(l);
ins(x,y,l);
}
root=; size=n; h[root]=INF;
getroot(,);
getans(root);
printf("%d\n",ans);
return ;
}

WA:deep要反过来求,d[x]表示以x为根的子树中黑点最长的路径(而不是从root到x经过了多少黑点)

  虽然好像原来的求法也能做不过不如这个方便(我一开始是写成两种混合了……QAQ)

RE:数组不能开20W,我改了个40W过了QAQ【iwtwiioi:双向边当然要开两倍的边集】!!!

 //SPOJ 1825
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
using namespace std;
inline void read(int &v){
v=; int sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
v*=sign;
}
/******************tamplate*********************/
const int N=,INF=1e8;
int n,m,k,root=,h[N],s[N],g[N],f[N],size,d[N];
bool vis[N],black[N];
int to[N],head[N],next[N],len[N],tot=;
inline void ins(int x,int y,int l){
to[++tot]=y; next[tot]=head[x]; head[x]=tot; len[tot]=l;
to[++tot]=x; next[tot]=head[y]; head[y]=tot; len[tot]=l;
} inline void getroot(int x,int fa){
s[x]=;h[x]=;
for(int i=head[x];i;i=next[i])
if (to[i]!=fa && !vis[to[i]]){
getroot(to[i],x);
s[x]+=s[to[i]];
//h[x]=max(h[x],s[to[i]]);
if (s[to[i]]>h[x]) h[x]=s[to[i]];
}
h[x]=max(h[x],size-s[x]);
if (h[x]<h[root]) root=x;
} inline void getdep(int x,int fa){
int res=;
s[x]=; d[x]=black[x];
for(int i=head[x];i;i=next[i]){
if (to[i]!=fa && !vis[to[i]]){
getdep(to[i],x);
res=max(res,d[to[i]]);
s[x]+=s[to[i]];
}
}
d[x]+=res;//x为根的子树的最大“深度”
}
inline void getg(int x,int fa,int leng,int c){
g[c]=max(g[c],leng);
for(int i=head[x];i;i=next[i])
if (to[i]!=fa && !vis[to[i]])
getg(to[i],x,leng+len[i],c+black[to[i]]);
} inline bool cmp(int x,int y){
return d[to[x]]<d[to[y]];
}
int ans=,st[N],cnt; inline void getans(int x){
vis[x]=;//vis=1保证递归搜索子树时不会搜到当前节点
//对根的出边按dep排序
cnt=;
for(int i=head[x];i;i=next[i]){
if (!vis[to[i]]){
getdep(to[i],x);
st[cnt++]=i;
}
}
sort(st,st+cnt,cmp);
F(i,,d[to[st[cnt-]]]) f[i]=-INF;
rep(i,cnt){
int y=to[st[i]];
F(j,,d[y]) g[j]=-INF;
getg(y,x,len[st[i]],black[y]);
if (i>){
int end=min(k-black[x],d[y]);
F(j,,end){
int p=min(d[to[st[i-]]],k-j-black[x]);
if (f[p]==-INF) break;//!!!这里没懂
if (g[j]!=-INF) ans=max(ans,g[j]+f[p]);
}
}
F(j,,d[y]){
f[j]=max(f[j],g[j]);
if (j) f[j]=max(f[j],f[j-]);
if (j+black[x]<=k) ans=max(ans,f[j]);
}
} for(int i=head[x];i;i=next[i])
if (!vis[to[i]]){
root=; size=s[to[i]];
getroot(to[i],x);
getans(root);
}
} int main(){
#ifndef ONLINE_JUDGE
freopen("1825.in","r",stdin);
#endif
read(n); read(k); read(m);
int x,y,l;
F(i,,m){ read(x); black[x]|=;}
F(i,,n){
read(x); read(y); read(l);
ins(x,y,l);
}
root=; size=n; h[root]=INF;
getroot(,);
getans(root);
printf("%d\n",ans);
return ;
}

调了一天半终于出来了!锻炼了耐心和静态查错能力~

【SPOJ】【1825】Free Tour 2的更多相关文章

  1. 【SPOJ】1825. Free tour II(点分治)

    http://www.spoj.com/problems/FTOUR2/ 先前看了一会题解就自己yy出来了...对拍过后交tle.................. 自己造了下大数据........t ...

  2. 【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)

    54  种草约翰有 N 个牧场,编号为 1 到 N.它们之间有 N − 1 条道路,每条道路连接两个牧场.通过这些道路,所有牧场都是连通的.刚开始的时候,所有道路都是光秃秃的,没有青草.约翰会在一些道 ...

  3. 【SPOJ】NUMOFPAL - Number of Palindromes(Manacher,回文树)

    [SPOJ]NUMOFPAL - Number of Palindromes(Manacher,回文树) 题面 洛谷 求一个串中包含几个回文串 题解 Manacher傻逼题 只是用回文树写写而已.. ...

  4. 【SPOJ】Substrings(后缀自动机)

    [SPOJ]Substrings(后缀自动机) 题面 Vjudge 题意:给定一个长度为\(len\)的串,求出长度为1~len的子串中,出现最多的出现了多少次 题解 出现次数很好处理,就是\(rig ...

  5. 【SPOJ】Longest Common Substring II (后缀自动机)

    [SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记 ...

  6. 【SPOJ】Longest Common Substring(后缀自动机)

    [SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另 ...

  7. 【SPOJ】Distinct Substrings(后缀自动机)

    [SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/e ...

  8. 【SPOJ】Distinct Substrings/New Distinct Substrings(后缀数组)

    [SPOJ]Distinct Substrings/New Distinct Substrings(后缀数组) 题面 Vjudge1 Vjudge2 题解 要求的是串的不同的子串个数 两道一模一样的题 ...

  9. 【SPOJ】Power Modulo Inverted(拓展BSGS)

    [SPOJ]Power Modulo Inverted(拓展BSGS) 题面 洛谷 求最小的\(y\) 满足 \[k\equiv x^y(mod\ z)\] 题解 拓展\(BSGS\)模板题 #inc ...

  10. 【SPOJ】QTREE7(Link-Cut Tree)

    [SPOJ]QTREE7(Link-Cut Tree) 题面 洛谷 Vjudge 题解 和QTREE6的本质是一样的:维护同色联通块 那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\) 每 ...

随机推荐

  1. NHibernate 错误

    Unable to locate persister for the entity named 'Model.Customer'.The persister define the persistenc ...

  2. Gitlab Issue Tracker and Wiki(二)

    一. 引用问题 1. 登陆 Gitlab服务器 2. 进入到super-git项目 3. 创建一个问题 4. 查看创建问题的号码,可以在下图找到. 5. 对代码进行提交去关闭这个问题,首先把项目在本机 ...

  3. 码云Android项目构建注意事项(转载)

    1.ant项目 build.xml必须位于项目根目录. 2.maven项目 pom.xml必须位于项目根目录. 3.gradle项目 由于gradle的配置灵活,我们做了一些规范,并且增加了一下机制来 ...

  4. Adobe Photoshop CC 2017-18.0安装教程

    Adobe Photoshop CC 2017-18.0安装教程 注:下载链接在文章后面 第一步:首先请将电脑的网络断开,很简单:禁用本地连接或者拔掉网线,这样就可以免除登录Creative Clou ...

  5. 分布式系统的烦恼------《Designing Data-Intensive Applications》读书笔记11

    使用分布式系统与在单机系统中处理问题有很大的区别,分布式系统带来了更大的处理能力和存储容量之后,也带来了很多新的"烦恼".在这一篇之中,我们将看看分布式系统带给我们新的挑战. 1. ...

  6. MXNet——symbol

    参考资料:有基础(Pytorch/TensorFlow基础)mxnet+gluon快速入门 symbol symbol 是一个重要的概念,可以理解为符号,就像我们平时使用的代数符号 x,y,z 一样. ...

  7. Graphviz 在 Windows 10 下 的 安装 Bug 解决方案

    报错: 解决方法: 参考:stackoverflow

  8. 打开tcp_tw_recycle引起的一次投诉分析

    背景: 我们有个基于oauth2.0协议给第三方授权以及信息的业务,年前对接入层.业务层做了次迁移.业务架构简单介绍下: lvs接入---> nginx ---> tomcat   问题: ...

  9. python 全排列

    itertools模块现成的全排列: for i in itertools.permutations('abcd',4): print ''.join(i) 相关全排列算法: def perm(l): ...

  10. leetcode 无重复字符的最长子串 python实现

    这道题需要借助哈希查找key的O(n) 时间复杂度, 否则就会超时 初始化一个 哈希表\字典  dic 头指针start 初始为0 当前指针 cur 初始为0 最大长度变量 l 初始为0 用cur变量 ...