spoj1825 Free tour II

题目链接

一道神奇的点分治

貌似有很多做法,我觉得BIT要好些一些(雾

要求经过黑点数<k就用BIT区间查询前缀

对于每个点用  BIT[0,k-经过黑点数]的最大值+路径长度

使用点分治做到O(n*log22n)

貌似还有O(nlog2n)的做法(雾

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<string>
  7 #include<cmath>
  8 #include<ctime>
  9 #include<queue>
 10 #include<stack>
 11 #include<map>
 12 #include<set>
 13 #define rre(i,r,l) for(int i=(r);i>=(l);i--)
 14 #define re(i,l,r) for(int i=(l);i<=(r);i++)
 15 #define Clear(a,b) memset(a,b,sizeof(a))
 16 #define inout(x) printf("%d",(x))
 17 #define douin(x) scanf("%lf",&x)
 18 #define strin(x) scanf("%s",(x))
 19 #define LLin(x) scanf("%lld",&x)
 20 #define op operator
 21 #define CSC main
 22 typedef unsigned long long ULL;
 23 typedef const int cint;
 24 typedef long long LL;
 25 using namespace std;
 26 cint inf=2147483647;
 27 void inin(int &ret)
 28 {
 29     ret=0;int f=0;char ch=getchar();
 30     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=1;ch=getchar();}
 31     while(ch>=‘0‘&&ch<=‘9‘)ret*=10,ret+=ch-‘0‘,ch=getchar();
 32     ret=f?-ret:ret;
 33 }
 34 int head[200020],next[400040],zhi[400040],w[200020],si[200020],v[400040],ed;
 35 int shu[200020],dis[200020],col[200020],bo[200020];
 36 int cc[200020],t[200020];
 37 int n,m,k,sum,ans,root,T;
 38 void add(int a,int b,int c)
 39 {
 40     next[++ed]=head[a],head[a]=ed,zhi[ed]=b,v[ed]=c;
 41     next[++ed]=head[b],head[b]=ed,zhi[ed]=a,v[ed]=c;
 42 }
 43 void getroot(int x,int fa)
 44 {
 45     w[x]=0,si[x]=1;
 46     for(int i=head[x];i;i=next[i])if(!bo[zhi[i]]&&zhi[i]!=fa)
 47     {
 48         getroot(zhi[i],x);
 49         si[x]+=si[zhi[i]];
 50         w[x]=max(w[x],si[zhi[i]]);
 51     }
 52     w[x]=max(w[x],sum-si[x]);
 53     if(w[x]<w[root])root=x;
 54 }
 55 int lowbit(int x){return x&-x;}
 56 int query(int r)
 57 {
 58     int ret=-inf;r++;
 59     while(r)
 60     {
 61         if(t[r]==T)ret=max(ret,cc[r]);
 62         r-=lowbit(r);
 63     }
 64     return ret;
 65 }
 66 void add_(int c,int x)
 67 {
 68     c++;
 69     while(c<=k+1)
 70     {
 71         if(t[c]==T)cc[c]=max(cc[c],x);
 72         else t[c]=T,cc[c]=x;
 73         c+=lowbit(c);
 74     }
 75 }
 76 void getans(int x,int fa)
 77 {
 78     if(shu[x]-col[root]>k)return ;
 79     int hh=query(k-shu[x]+col[root]);
 80     if(hh!=-inf)ans=max(ans,hh+dis[x]);
 81     for(int i=head[x];i;i=next[i])if(!bo[zhi[i]]&&zhi[i]!=fa)
 82         dis[zhi[i]]=dis[x]+v[i],shu[zhi[i]]=col[zhi[i]]+shu[x],getans(zhi[i],x);
 83 }
 84 void add(int x,int fa)
 85 {
 86     if(shu[x]-col[root]>k)return ;
 87     add_(shu[x],dis[x]);
 88     for(int i=head[x];i;i=next[i])if(!bo[zhi[i]]&&zhi[i]!=fa)
 89         add(zhi[i],x);
 90 }
 91 void solve(int x)
 92 {
 93     T++;
 94     bo[x]=1;add_(col[x],0);
 95     for(int i=head[x];i;i=next[i])if(!bo[zhi[i]])
 96     {
 97         shu[zhi[i]]=col[x]+col[zhi[i]],dis[zhi[i]]=v[i];
 98         getans(zhi[i],x);
 99         add(zhi[i],x);
100     }
101     for(int i=head[x];i;i=next[i])if(!bo[zhi[i]])
102         root=0,sum=si[zhi[i]],getroot(zhi[i],0),solve(root);
103 }
104 int CSC()
105 {
106     inin(n),inin(k),inin(m);
107     re(i,1,m)
108     {
109         int x;inin(x);
110         col[x]=1;
111     }
112     re(i,2,n)
113     {
114         int q,w,e;
115         inin(q),inin(w),inin(e);
116         add(q,w,e);
117     }
118     w[0]=sum=n;
119     getroot(1,0);
120     re(i,1,k+1)cc[i]=-inf;
121     ans=-inf;
122     solve(root);
123     printf("%d",max(ans,0));
124     return 0;
125 }
时间: 2024-10-15 06:58:28

spoj1825 Free tour II的相关文章

SPOJ1825 Free tour II 树分治

题意:带边权树上有白点和黑点,问你最多不经过k个黑点使得路径最长(注意,路径有负数) 解题思路:基于树的点分治.数的路径问题,具体看09QZC论文,特别注意 当根为黑时的情况 解题代码: 1 // File Name: spoj1825.cpp 2 // Author: darkdream 3 // Created Time: 2014年10月05日 星期日 20时20分33秒 4 5 #include<vector> 6 #include<list> 7 #include<

SPOJ1825 FTOUR2 - Free tour II

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description After the success of 2nd anniversary (take a look at problem FTOUR for more details), this 3rd year, Travel Agent SP

SPOJ1825/FTOUR2:Free tour II——包看得懂/看不懂题解

http://www.spoj.com/problems/FTOUR2/en/ 题目大意:给一棵黑白染色的树,求边权和最大且经过黑点不超过K的路径. ———————————————————— 前排膜拜hzwer,借(抄)鉴(袭)了神犇的代码与思路,要看简洁的思路的话:http://hzwer.com/5984.html 然而……就算是抄了代码,还是没懂这题怎么做怎么办? 别着急,这道神神神题慢慢来. —————————————————————— 首先判断我们要放什么板子,很显然我们想到的是和树有

SPOJ1825:Free tour II

题意 luogu的翻译 给定一棵n个点的树,树上有m个黑点,求出一条路径,使得这条路径经过的黑点数小于等于k,且路径长度最大 Sol 点分治辣 如果是等于\(k\)的话,开个桶取\(max\)就好了 而小于等于\(k\),就可以把桶换成树状数组,求前缀\(max\) 很慢能过 # include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a))

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

http://www.spoj.com/problems/FTOUR2/ 先前看了一会题解就自己yy出来了...对拍过后交tle.................. 自己造了下大数据........tle......................... what? 明早更新吧..调到吐了.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include &l

SPOJ 1825 FTOUR2 - Free tour II (树上点分治)

题目地址:SPOJ 1825 树分治的题果然除了模板题就是金牌题啊...这题是一道论文题,想了好长时间....终于过了,,,,注意一个坑点,如果权值全部为负的话,是可以不选任意一条边的,这样权值为0...也就是说初始值要设为0... 具体看漆子超的论文<分治算法在树的路径问题中的应用>.. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue>

[SP1825] Free tour II

/* ----------------------- [题解] https://www.luogu.org/blog/IRving1-1/solution-sp1825 ----------------------- O(Nlog^2)做法,vjudge上写的是时限100ms,过2e5数据 ----------------------- 统计tmp[i]为有i个黑点的最长路径,进行转移 合并的顺序很巧妙,也很重要,这里倒序枚举当前子树的j(tmp[j]),则可以做到控制维护之前子树cur(max

SP1825 【FTOUR2 - Free tour II】

# \(SP1825\) 看到没有人用老师的办法,于是自己写一下思路 思路第一步:排除旧方法 首先这道题和\(4178\)不一样,因为那道题是计数,而这道题是求最值,最值有个坏处,就是对于来自相同子树的信息没法高效剔除,比如容斥用不了,举例来说,对于这道题,如果我们继续用尺取法维护黑点个数,对于一组刚好使\(cnt_l+cnt_r\leq k\)的\(l,r\),且\([l+1,r]\)所在子树都与\(l\)不同时就可以选取\(l~and~x\in [l+1,r]\),我们要使\(dis_l+d

12月刷题总结

各种被屠...学东西各种慢... QAQ 字符串: sam: [SPOJ]7258. Lexicographical Substring Search(后缀自动机) [SPOJ]1812. Longest Common Substring II(后缀自动机) [BZOJ]2555: SubString(后缀自动机) [BZOJ]3172: [Tjoi2013]单词(后缀自动机) [wikioi]3160 最长公共子串(后缀自动机) lcp: [BZOJ]1014: [JSOI2008]火星人pr