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 ...
随机推荐
- 快看Sample代码,速学Swift语言(3)-运算符
运算符是用来检查,更改或组合值的特殊符号或短语.Swift提供的很多常规的运算符,如+.-.*./.%.=.==等,以及逻辑运算的&&.||等等,基本上不需要重复介绍,我们在这里只需要 ...
- hibernate多对多的更新问题
错误原因 A different ]; nested exception ]] with root cause org.hibernate.NonUniqueObjectException: A di ...
- 现代程序设计 homework-06
写代码爽还是读代码爽? 当然是写代码爽好吧... 读代码明显是读+写两倍的工作量好么... 本次作业要求: 1) 把程序编译通过, 跑起来. 读懂程序,在你觉得比较难懂的地方加上一些注释,这样大家就能 ...
- java异常Exception
学习笔记: 一.程序的异常:Throwable 严重问题:Error ,我们不处理.这种问题一般很严重,不如内存溢出 问题:Exception 编译问题:不是RuntimeException异常.必须 ...
- storm问题汇总
1.删除了本地topology导致无法启动nimbus 删除storm的自定义的库中的数据 删除zookeeper中配置的dataDir中的数据 重启服务即可
- findBugs安装
点击“Help->InstallNew Software”,如下图所示: 2 接着如下图所示: 3 Name”输入“findBugs”,“Location”输入“http://findbugs. ...
- [转帖]2015年时微软Win3.1崩溃迫使巴黎奥利机场短暂关闭
https://www.ithome.com/html/it/188796.htm IT之家讯 2015年11月14日消息,上周法国巴黎奥利机场因为微软的Windows 3.1系统出现故障不得不迫使所 ...
- Linux 下面 Sqlserver 2017 的简单安装
1. 公司网络太烂 yum 在线安装失败 2. 解决方法 找微软的官网 百度网盘 离线下载rpm包. https://packages.microsoft.com/rhel/7/mssql-serve ...
- java随笔4 java中接参整形转字符串
通过+‘’来实现
- js如何复制一个对象?
方法一: 把原来对象的属性遍历一遍,赋给一个新的对象. //深复制对象方法 var cloneObj = function (obj) { var newObj = {}; if (obj insta ...