BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)
题目描述
输入
输出
样例输入
1 5 2
1 2 4
2 3 6
2 4 5
样例输出
5
10
9
6
提示
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int root[15010];
int froot[15010];
int ls[6000010];
int rs[6000010];
int sum[6000010];
int n,k;
int x,y,z;
int tot;
int num;
int dfn;
int f[15010];
int g[30010][16];
int lg[30010];
int dep[15010];
int val[30010];
int to[30010];
int next[30010];
int head[15010];
int size[15010];
int s[15010];
int rot;
int cnt;
int mx[15010];
int ans;
int vis[15010];
int l,r;
inline void add(int x,int y,int z)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
val[tot]=z;
}
inline void dfs(int x,int fa)
{
g[++dfn][0]=dep[x];
s[x]=dfn;
for(int i=head[x];i;i=next[i])
{
if(to[i]!=fa)
{
dep[to[i]]=dep[x]+val[i];
dfs(to[i],x);
g[++dfn][0]=dep[x];
}
}
}
inline void getroot(int x,int fa)
{
size[x]=1;
mx[x]=0;
for(int i=head[x];i;i=next[i])
{
if(!vis[to[i]]&&to[i]!=fa)
{
getroot(to[i],x);
size[x]+=size[to[i]];
mx[x]=max(mx[x],size[to[i]]);
}
}
mx[x]=max(mx[x],num-size[x]);
if(mx[x]<mx[rot])
{
rot=x;
}
}
inline int lca(int x,int y)
{
x=s[x];
y=s[y];
if(x>y)
{
swap(x,y);
}
int len=lg[y-x+1];
return min(g[x][len],g[y-(1<<len)+1][len]);
}
inline int dis(int x,int y)
{
return dep[x]+dep[y]-2*lca(x,y);
}
inline void partation(int x)
{
vis[x]=1;
for(int i=head[x];i;i=next[i])
{
if(!vis[to[i]])
{
num=size[to[i]];
rot=0;
getroot(to[i],0);
f[rot]=x;
partation(rot);
}
}
}
inline void change(int &rt,int l,int r,int k)
{
if(!rt)
{
rt=++cnt;
}
sum[rt]++;
if(l==r)
{
return ;
}
int mid=(l+r)>>1;
if(k<=mid)
{
change(ls[rt],l,mid,k);
}
else
{
change(rs[rt],mid+1,r,k);
}
}
inline int query(int rt,int l,int r,int k)
{
if(!rt||k<0)
{
return 0;
}
if(l==r)
{
return sum[rt];
}
int mid=(l+r)>>1;
if(k<=mid)
{
return query(ls[rt],l,mid,k);
}
else
{
return sum[ls[rt]]+query(rs[rt],mid+1,r,k);
}
}
inline int check(int val,int x)
{
int res=0;
for(int i=x;i;i=f[i])
{
res+=query(root[i],0,150000,val-dis(x,i));
}
for(int i=x;f[i];i=f[i])
{
res-=query(froot[i],0,150000,val-dis(x,f[i]));
}
return res;
}
int main()
{
scanf("%d%d",&n,&k);
k++;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
dfs(1,0);
for(int i=2;i<=dfn;i++)
{
lg[i]=lg[i>>1]+1;
}
for(int j=1;j<=15;j++)
{
for(int i=1;i<=dfn;i++)
{
if(i+(1<<j)-1>dfn)
{
break;
}
g[i][j]=min(g[i][j-1],g[i+(1<<(j-1))][j-1]);
}
}
mx[0]=1<<30;
num=n;
rot=0;
getroot(1,0);
partation(rot);
for(int x=1;x<=n;x++)
{
for(int i=x;i;i=f[i])
{
change(root[i],0,150000,dis(x,i));
}
for(int i=x;f[i];i=f[i])
{
change(froot[i],0,150000,dis(x,f[i]));
}
}
for(int i=1;i<=n;i++)
{
l=0;
r=150000;
ans=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid,i)>=k)
{
ans=mid;
r=mid-1;
}
else
{
l=mid+1;
}
}
printf("%d\n",ans);
}
}
点分树+vector
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
vector<int>sum[100010];
vector<int>fsum[100010];
int n,k;
int x,y,z;
int tot;
int num;
int dfn;
char ch[3];
int f[100010];
int g[200010][17];
int lg[200010];
int dep[100010];
int val[200010];
int to[200010];
int next[200010];
int head[100010];
int size[100010];
int s[100010];
int rot;
int cnt;
int mx[100010];
int ans;
int vis[100010];
int l,r;
int length;
void add(int x,int y,int z)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
val[tot]=z;
}
void dfs(int x,int fa)
{
g[++dfn][0]=dep[x];
s[x]=dfn;
for(int i=head[x];i;i=next[i])
{
if(to[i]!=fa)
{
dep[to[i]]=dep[x]+val[i];
dfs(to[i],x);
g[++dfn][0]=dep[x];
}
}
}
void getroot(int x,int fa)
{
size[x]=1;
mx[x]=0;
for(int i=head[x];i;i=next[i])
{
if(!vis[to[i]]&&to[i]!=fa)
{
getroot(to[i],x);
size[x]+=size[to[i]];
mx[x]=max(mx[x],size[to[i]]);
}
}
mx[x]=max(mx[x],num-size[x]);
if(mx[x]<mx[rot])
{
rot=x;
}
}
int lca(int x,int y)
{
x=s[x];
y=s[y];
if(x>y)
{
swap(x,y);
}
int len=lg[y-x+1];
return min(g[x][len],g[y-(1<<len)+1][len]);
}
int dis(int x,int y)
{
return dep[x]+dep[y]-(lca(x,y)<<1);
}
void partation(int x)
{
vis[x]=1;
for(int i=head[x];i;i=next[i])
{
if(!vis[to[i]])
{
num=size[to[i]];
rot=0;
getroot(to[i],0);
f[rot]=x;
partation(rot);
}
}
}
int check(int val,int x)
{
int res=0;
for(int i=x;i;i=f[i])
{
res+=upper_bound(sum[i].begin(),sum[i].end(),val-dis(x,i))-sum[i].begin();
}
for(int i=x;f[i];i=f[i])
{
res-=upper_bound(fsum[i].begin(),fsum[i].end(),val-dis(x,f[i]))-fsum[i].begin();
}
return res;
}
int main()
{
scanf("%s",ch);
scanf("%d%d",&n,&k);
k++;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
length+=z;
add(x,y,z);
add(y,x,z);
}
dfs(1,0);
for(int i=2;i<=dfn;i++)
{
lg[i]=lg[i>>1]+1;
}
for(int j=1;j<=16;j++)
{
for(int i=1;i<=dfn;i++)
{
if(i+(1<<j)-1>dfn)
{
break;
}
g[i][j]=min(g[i][j-1],g[i+(1<<(j-1))][j-1]);
}
}
mx[0]=1<<30;
num=n;
rot=0;
getroot(1,0);
partation(rot);
for(int x=1;x<=n;x++)
{
for(int i=x;i;i=f[i])
{
sum[i].push_back(dis(i,x));
}
for(int i=x;f[i];i=f[i])
{
fsum[i].push_back(dis(f[i],x));
}
}
for(int i=1;i<=n;i++)
{
sort(sum[i].begin(),sum[i].end());
sort(fsum[i].begin(),fsum[i].end());
}
for(int i=1;i<=n;i++)
{
l=0;
r=length;
ans=-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid,i)>=k)
{
ans=mid;
r=mid-1;
}
else
{
l=mid+1;
}
}
printf("%d\n",ans);
}
}
BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)的更多相关文章
- BZOJ2117: [2010国家集训队]Crash的旅游计划
裸点分,点分树每层维护有序表,查询二分,复杂度$O(nlog^3n)$. #include<bits/stdc++.h> #define M (u+v>>1) #define ...
- 【BZOJ2117】 [2010国家集训队]Crash的旅游计划
[BZOJ2117] [2010国家集训队]Crash的旅游计划 Description 眼看着假期就要到了,Crash由于长期切题而感到无聊了,因此他决定利用这个假期和好友陶陶一起出去旅游. Cra ...
- [BZOJ2051]A Problem For Fun/[BZOJ2117]Crash的旅游计划/[BZOJ4317]Atm的树
[BZOJ2051]A Problem For Fun/[BZOJ2117]Crash的旅游计划/[BZOJ4317]Atm的树 题目大意: 给出一个\(n(n\le10^5)\)个结点的树,每条边有 ...
- [BZOJ2117]Crash的旅游计划
Description 眼看着假期就要到了,Crash由于长期切题而感到无聊了,因此他决定利用这个假期和好友陶陶一起出去旅游. Crash和陶陶所要去的城市里有N (N > 1) 个景点,Cra ...
- bzoj3730 震波 [动态点分治,树状数组]
传送门 思路 如果没有强制在线的话可以离线之后CDQ分治随便搞. 有了强制在线之后--可能可以二维线段树?然而我不会算空间. 然后我们莫名其妙地想到了动态点分治,然后这题就差不多做完了. 点分树有一个 ...
- 【BZOJ3110】K大数查询(权值线段树套线段树+标记永久化,整体二分)
题意:有N个位置,M个操作.操作有两种,每次操作 如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是 ...
- 主席树/线段树模拟归并排序+二分答案(好题)——hdu多校第4场08
用主席树写起来跑的快一点,而且也很傻比,二分答案,即二分那个半径就行 主席树求的是区间<=k的个数 #include<bits/stdc++.h> using namespace s ...
- ZJOI 2017 树状数组(线段树套线段树)
题意 http://uoj.ac/problem/291 思路 不难发现,九条カレン醬所写的树状数组,在查询区间 \([1,r]\) 的时候,其实在查询后缀 \([r,n]\) :在查询 \([l,r ...
- BZOJ4552 HEOI/TJOI2016 排序 线段树、二分答案
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 题意:给出一个$1$到$N$的全排列,对其进行$M$次排序,每次排序将区间$[l ...
随机推荐
- 在IDEA中构建Tomcat项目流程
在IDEA中构建Web项目流程 打开你的IDEA,跟着我走! 第一步:新建项目 第二步:找到Artifacts 点击绿色的+号,如图所示,点一下 这一步很关键,目的是设置输出格式为war包,如果你的项 ...
- SpringBoot热部署的实现方式
一:热部署的实现 1.使用Spring-boot-devtools 2.使用Spring Loaded 二:devtools(推荐) 一般情况下直接在pom.xml文件添加下面的依赖即可,但eclip ...
- 2小时学会Spring Boot(IDE:eclipse)
一:安装STS插件 官网下载:点此下载STS 注意:STS版本必须与eclipse版本对应 安装教程:http://blog.csdn.net/cryhelyxx/article/details/53 ...
- 2018年Java生态行业报告
0 Java版本使用占比 毫无疑问,Java8被广泛用于生产环境! Java 9和Java 10的使用率非常低,不到5%. 2017年,Java 7和更早的版本的数量大约是24.4%,现在是10. ...
- Makefile有三个非常有用的变量。分别是$@,$^,$
原文地址:https://blog.csdn.net/u013774102/article/details/79043559 假设我们有下面这样的一个程序,源代码如下: /* main.c */ #i ...
- Beta阶段团队成员贡献分分配规则
Beta阶段团队成员贡献分分配规则 Alpha阶段贡献分分配有些负责,在这里进行一些修改: 对任务完成得分部分进行了简化 对发现bug的惩罚措施进行了修改 移除了优化得分,不鼓励修改他人代码 移除了帮 ...
- 消息队列queue
一.queue 在多线程编程中,程序的解耦往往是一个麻烦的问题,以及在socket网络编程中也会有这样的问题.recv 和send之间,如果服务端有消息,问题需要发送给客户端,而那边的recv 被主程 ...
- CentOS搭建OpenVPN以及WIN&Android&iOS的安装连接
OpenVPNhttp://info.swufe.edu.cn/vpn/openvpn/#2 苹果.安卓智能手机openvpn的设置_百度经验https://jingyan.baidu.com/art ...
- 完美解决safari、微信浏览器下拉回弹效果
CSS代码: .box{ overflow: auto; -webkit-overflow-scrolling: touch; } HTML代码: <body class="box&q ...
- 【转帖】Linux的历史----Linux内核剖析(一)
Linux的历史----Linux内核剖析(一) 2015年04月09日 10:51:09 JeanCheng 阅读数:11351更多 所属专栏: Linux内核剖析 版权声明:本文为博主原创文 ...