SPOJ - FTOUR2 (点分治+树状数组)
题目:https://vjudge.net/contest/307753#problem/I
题意:有一颗树,上面有白色黑色点,每个点上有一个权值,权值可以为负,现在我要求一条路径,权值和最大,这条路径满足 白色可以随便经过多少个,黑色点的个数必须<=m
思路:首先又是树上路径题,必然点分治,其实这个题我们在考虑当前子树路径时,我们找前面子树出现过并且黑色出现数<=m-当前黑色节点数 里面出现的最大值这样的一条路径。
举个栗子: 限制路径黑色数:5
当前子树下的黑色数 :2 权值 5
(前面子树出现数)
黑色数 0 1 2 3 4 5
权值 1 6 2 4 7 3
我们就应该在 0-3黑色数里面寻找最大值 ,我们找到了6,所以可以更新最大值为 6+5
还有我们对于这条路径黑色数已经超过要求的可以不再搜下去,因为这本身就不符合要求了,下面子树的肯定也不符合。
所以现在我们的问题转化为如何在前面子树固定黑色数中找到最大值,我们还要记得把当前子树访问完后与前面子树合并,因为一个固定黑色数我们保留最大值即可,其实我们可以把黑色数转化为一个区间,然后区间找最大值,所以我们可以用到树状数组,但是我们非常非常要注意的是->
!!!注意:因为我们找重心已经是O(n)了,然后我们在重心里面的操作不能是O(n)的,但是我们要清空树状数组要O(n),就成了O(n^2)了,我们要怎么优化呢,>_<,之前我就是没想清楚这里的时间复杂度然后超时了,这里我们只能也是log的,怎么办呢,我们记录下来我们之前操作了哪些点,然后再置0即可,但是树状数组操作的点是以二进制的,这又是第二次犯蠢的地方,我最开始直接把那个路径出现的点去置0了,但是因为树状数组要向上界更新最大值,所以不止更改了这些点,所以要怎么搞呢>_<, 其实就是把记录改的点放在树状数组update操作里面即可,我真的傻了>_<
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#define maxn 200005
#define mod 0x3f3f3f3f
using namespace std;
typedef long long ll;
ll da;
vector<pair<ll,ll> > mp[maxn],xx[maxn];//存下图
pair<ll,ll> e[maxn];
ll e2[*maxn];
bool vis[maxn];//标记曾经使用过的重心
ll maxsize[maxn],dis[maxn],d[maxn],flag[maxn],yj[maxn];//maxsize 当前节点的最大子树
ll siz[maxn],xd[maxn];// dis 到重心的距离 d 出现过的距离
ll n,m,k,rt,sum,qe,qe2,ans1,ans2; // siz 当前节点的子树个数 e 出现的距离 rt代表当前重心
void find(ll x,ll f){//找出重心
siz[x]=;
maxsize[x]=;
for(int i=;i<mp[x].size();i++){
pair<ll,ll> q=mp[x][i];
if(q.first==f||vis[q.first]) continue;//vis数组标记曾经使用过的重心
find(q.first,x);
siz[x]+=siz[q.first];
maxsize[x]=max(maxsize[x],siz[q.first]);
}
maxsize[x]=max(maxsize[x],sum-siz[x]);//节点总数减去当前的子树数=以当前节点为根的父亲点子树数
if(maxsize[x]<maxsize[rt]){
rt=x;
}
}
void query(ll z,ll sm){
if(z>ans1){
ans1=z;
ans2=sm;
}
else if(z==ans1){
ans2+=sm;
}
}
ll lowbit(ll x){
return x&(-x);
}
void update(ll x,ll y){
while(x<=m){
e2[qe2++]=x;
flag[x]=max(flag[x],y);
x+=lowbit(x);
}
}
ll query(ll x){
ll ans=;
while(x){
ans=max(ans,flag[x]);
x-=lowbit(x);
}
return ans;
}
void get_dis(ll x,ll f,ll len,ll yjs,ll root){ if(yjs<=m) ans1=max(ans1,len);
else return; ll t=m-yjs;
if(yj[root]) t++;
ans1=max(ans1,len+query(t+));
e[qe].first=yjs;
e[qe].second=len;
qe++;
for(int i=;i<mp[x].size();i++){
pair<ll,ll> q=mp[x][i];
if(q.first==f||vis[q.first]) continue;
//dis[q.first]=(dis[x]+len)%3;
get_dis(q.first,x,len+q.second,yjs+yj[q.first],root);
}
}
void divide(ll x){
vis[x]=;
//printf("rt=%lld ans1=%lld\n",x,ans1);
for(int i=;i<mp[x].size();i++){
pair<ll,ll> q=mp[x][i];
qe=;
if(vis[q.first]) continue;
//dis[x]=q.second;
get_dis(q.first,x,q.second,yj[x]+yj[q.first],x);
for(int j=;j<qe;j++){
update(e[j].first+,e[j].second);
}
}
for(int i=;i<qe2;i++){
flag[e2[i]]=;
}
qe2=;
for(int i=;i<mp[x].size();i++){
pair<ll,ll> q=mp[x][i];
if(vis[q.first]) continue;
//if(da>0) break;
sum=siz[q.first];
rt=;
maxsize[rt]=mod;
find(q.first,x);
divide(rt);
}
// vis[x]=0;
}
void init(){
ans1=;ans2=;
for(int i=;i<=n+;i++) mp[i].clear();
for(int i=;i<=n+;i++) vis[i]=;
for(int i=;i<=n+;i++) flag[i]=;
for(int i=;i<=n+;i++) yj[i]=;
}
int main(){
ll t;
while(scanf("%lld%lld%lld",&n,&m,&k)!=EOF){
ll a,b,c;
init();
ll xx;
for(int i=;i<=k;i++){
scanf("%lld",&xx);
yj[xx]=;
}
for(int i=;i<=n-;i++){
scanf("%lld%lld%lld",&a,&b,&c);
mp[a].push_back(make_pair(b,c));
mp[b].push_back(make_pair(a,c));
}
sum=n;//当前节点数
rt=;
maxsize[]=mod;//置初值
find(,);
divide(rt);
printf("%lld\n",ans1);
}
}
SPOJ - FTOUR2 (点分治+树状数组)的更多相关文章
- BZOJ_2225_[Spoj 2371]Another Longest Increasing_CDQ 分治+树状数组
BZOJ_2225_[Spoj 2371]Another Longest Increasing_CDQ 分治+树状数组 Description 给定N个数对(xi, yi),求最长上升子 ...
- 【bzoj2225】[Spoj 2371]Another Longest Increasing CDQ分治+树状数组
题目描述 给定N个数对(xi, yi),求最长上升子序列的长度.上升序列定义为{(xi, yi)}满足对i<j有xi<xj且yi<yj. 样例输入 8 1 3 3 2 1 1 4 5 ...
- BZOJ_3262_陌上花开_CDQ分治+树状数组
BZOJ_3262_陌上花开_CDQ分治+树状数组 Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),用三个整数表示. 现在要对每朵花评级,一朵花的级别是它拥有的 ...
- 【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组
[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...
- BZOJ 1176 Mokia CDQ分治+树状数组
1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1854 Solved: 821[Submit][St ...
- 【bzoj3262】陌上花开 CDQ分治+树状数组
题目描述 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa&g ...
- BZOJ_2253_[2010 Beijing wc]纸箱堆叠 _CDQ分治+树状数组
BZOJ_2253_[2010 Beijing wc]纸箱堆叠 _CDQ分治+树状数组 Description P 工厂是一个生产纸箱的工厂.纸箱生产线在人工输入三个参数 n p a , , 之后, ...
- BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组
BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一 ...
- BZOJ_2683_简单题&&BZOJ_1176_[Balkan2007]Mokia_CDQ分治+树状数组
BZOJ_2683_简单题&&BZOJ_1176_[Balkan2007]Mokia_CDQ分治+树状数组 Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加 ...
- BZOJ 2683 简单题 cdq分治+树状数组
题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后.二维的数据结构是显然不能过的.于是我们可能会考虑把一维排序之后还有一位上数据结构什么的,然而cdq分治却可以非常好 ...
随机推荐
- 测开之路六十四:UI测试平台之前端页面
{% extends "base.html" %} {% block script %} <!-- 引入js文件,需要在base.html留入口,不然渲染会出问题. --&g ...
- iframe父窗口和子窗口的调用方法
iframe 父窗口和子窗口的调用方法父窗口调用子窗口 iframe_name.iframe_document_object.object_attribute = attribute_value 例子 ...
- Mac003--Maven安装与环境变量配置
Mac--Maven安装 一.应用brew安装maven及安装位置 打开终端,输入命令:brew install maven 参考博客:https://www.jianshu.com/p/230e0b ...
- 简单谈谈Netty的高性能之道
传统RPC 调用性能差的三宗罪 网络传输方式问题:传统的RPC 框架或者基于RMI 等方式的远程服务(过程)调用采用了同步阻塞IO,当客户端的并发压力或者网络时延增大之后,同步阻塞IO 会由于频繁的w ...
- Spring自动装配之依赖注入(DI)
依赖注入发生的时间 当Spring IOC 容器完成了Bean 定义资源的定位.载入和解析注册以后,IOC 容器中已经管理类Bean定义的相关数据,但是此时IOC 容器还没有对所管理的Bean 进行依 ...
- [BZOJ3622] 已经没有什么好害怕的了(dp+容斥)
Description: 有两个数组a和b,两两配对,求 \(a_i>b_i\) 的配对比 \(b_i>a_i\) 的配对多 \(k\) 个的方案数 \(k\le n\le 2000\ ...
- 线段树(two value)与树状数组(RMQ算法st表)
士兵杀敌(三) 时间限制:2000 ms | 内存限制:65535 KB 难度:5 描述 南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比 ...
- [BZOJ1604][Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 (Treap+单调队列)
题面 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个"群".每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi( ...
- 数据库之Query Builder
Yii的查询构造器提供了一个用面向对象的方法来构造SQL语句.他让开发人员可以用类的方法,属性来作为SQL语句的一部分.然后把不同部分组装到一个正确的SQL语句中,调用DAO的方法来执行.下面的例子演 ...
- Redis数据库-基础篇
Redis Redis是一个开源的,先进的key-value存储. 它通常被称为数据结构服务器,因为键可以包含字符串,哈希,链表,集合和有序集合. Redis 简介 Redis 是完全开源免费的,遵守 ...