COJ 0346 WZJ的旅行(二)更新动态树分治版本
| WZJ的旅行(二) |
| 难度级别:D; 运行时间限制:3000ms; 运行空间限制:51200KB; 代码长度限制:2000000B |
|
试题描述
|
|
时隔多日,WZJ又来到了幻想国旅行。幻想国由N个城市组成,由于道路翻修,只有N-1条双向道路可以通行,第i条双向道路从ui连接到vi,距离为wi。但这N-1条道路竟然连接了整个国家,每两个城市之间都有一条道路! WZJ知道这里景点很多,所以他想从城市s出发到城市t,旅游所有沿途的城市。WZJ想起到锻炼作用,但又不想太累,所以城市s到城市t的距离必须在L到R之间。另外WZJ规定s必须小于t,你能帮助他统计有多少对城市(s,t)符合要求吗? |
|
输入
|
|
第一行为三个正整数N,L,R。
接下来N-1行每行为三个正整数ui,vi,wi。 |
|
输出
|
|
输出多少对城市(s,t)符合要求。
|
|
输入示例
|
|
5 3 6
1 2 3 2 3 3 3 4 2 4 5 1 |
|
输出示例
|
|
6
|
|
其他说明
|
|
城市对(1,2)、(2,3)、(1,3)、(2,4)、(2,5)、(3,5)均符合要求,共计6对
1<=N<=100000 1<=L<=R<=10^9 1<=ui,vi<=N 1<=wi<=1000 |
题解:会写点分治了。。。
首先补集转换,不在同一个子树的 = 总的 - 在同一个子树的,那么就是求路径两段在同一个子树的,dfs一遍排序再金鸡独立大法求前缀,转成区间,然后就没了。
意会一下。。。(逃。。。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define PAU putchar(' ')
#define ENT putchar('\n')
using namespace std;
const int maxn=+,inf=-1u>>;
struct ted{int x,y,w;ted*nxt;}adj[maxn<<],*fch[maxn],*ms=adj;
void add(int w,int y,int x){
*ms=(ted){x,y,w,fch[x]};fch[x]=ms++;
*ms=(ted){y,x,w,fch[y]};fch[y]=ms++;
return;
}
bool vis[maxn];
int L,R,CG=,siz[maxn],f[maxn],n,size;
void findcg(int x,int fa){
int mxs=-inf;siz[x]=;
for(ted*e=fch[x];e;e=e->nxt){
int v=e->y;if(v!=fa&&!vis[v]){
findcg(v,x);siz[x]+=siz[v];
mxs=max(mxs,siz[v]);
}
}f[x]=max(mxs,size-siz[x]);
if(f[x]<f[CG])CG=x;return;
}
long long ans;
int A[maxn],dep[maxn],cnt;
void dfs(int x,int fa,int dist){
A[cnt++]=dist;
for(ted*e=fch[x];e;e=e->nxt){
int v=e->y;if(v!=fa&&!vis[v])dfs(v,x,dist+e->w);
}return;
}
long long cal(int x,int base){
cnt=;dfs(x,,base);long long res=;
sort(A,A+cnt);
int l=,r=cnt-;while(l<r)if(A[l]+A[r]>R)r--;else res+=r-l++;
l=;r=cnt-;while(l<r)if(A[l]+A[r]>=L)r--;else res-=r-l++;
return res;
}
void solve(int x){
vis[x]=true;ans+=cal(x,);
for(ted*e=fch[x];e;e=e->nxt){
int v=e->y;if(!vis[v]){
ans-=cal(v,e->w);
f[CG=]=inf;size=siz[v];findcg(v,);
solve(CG);
}
}return;
}
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') sig=-;ch=getchar();}
while(isdigit(ch)) x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(long long x){
if(x==){putchar('');return;}if(x<) putchar('-'),x=-x;
int len=;long long buf[];while(x) buf[len++]=x%,x/=;
for(int i=len-;i>=;i--) putchar(buf[i]+'');return;
}
void init(){
n=read();L=read();R=read();
for(int i=;i<n;i++)add(read(),read(),read());
f[CG=]=inf;size=n;findcg(,);
solve(CG);write(ans);
return;
}
void work(){
return;
}
void print(){
return;
}
int main(){
init();work();print();return ;
}
当然窝萌还可以写动态树分治对不对,维护两个treap就是常数有点大耶。
要注意一点:cal函数只需要query就行了,不需要重新计算一遍!!!
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<ctime>
#define PAU putchar(' ')
#define ENT putchar('\n')
#define CH for(int d=0;d<2;d++)if(ch[d])
using namespace std;
const int maxn=+,maxq=+,maxnode=+,maxm=+,inf=-1u>>;
struct node{
node*ch[];int r,siz,v;
void init(){r=rand();siz=;ch[]=ch[]=NULL;return;}
void update(){siz=;CH{siz+=ch[d]->siz;}return;}
}treap[maxnode],*nodecnt=treap,*cha[maxn],*tre[maxn];
node*newnode(){node*x=nodecnt++;x->init();return x;}
void rotate(node*&x,int d){
node*k=x->ch[d^];x->ch[d^]=k->ch[d];k->ch[d]=x;x->update();k->update();x=k;return;
}
void insert(node*&x,int v){
if(!x)x=newnode(),x->v=v;
else{int d=v>x->v;insert(x->ch[d],v);
if(x->r<x->ch[d]->r)rotate(x,d^);else x->update();
}return;
}
int find(node*x,int v){
if(!x)return ;
if(v<=x->v)return find(x->ch[],v);
else return (x->ch[]?x->ch[]->siz:)++find(x->ch[],v);
}
struct ted{int x,y,w;ted*nxt;}adj[maxm],*fch[maxn],*ms=adj;
void add(int x,int y,int w){
*ms=(ted){x,y,w,fch[x]};fch[x]=ms++;
*ms=(ted){y,x,w,fch[y]};fch[y]=ms++;
return;
}
int mi[maxq][],Log[maxq],dep[maxn],pos[maxn],cnt;
void build(int x,int fa,int dis){
mi[++cnt][]=dep[x]=dis;pos[x]=cnt;
for(ted*e=fch[x];e;e=e->nxt){
int v=e->y;if(v!=fa)build(v,x,dis+e->w),mi[++cnt][]=dep[x];
}return;
}
void initrmq(){
Log[]=-;for(int i=;i<=cnt;i++)Log[i]=Log[i>>]+;
for(int j=;(<<j)<=cnt;j++)
for(int i=;i+(<<j)-<=cnt;i++)
mi[i][j]=min(mi[i][j-],mi[i+(<<j-)][j-]);return;
}
int dist(int x,int y){
int ans=dep[x]+dep[y];x=pos[x];y=pos[y];if(x>y)swap(x,y);
int k=Log[y-x+];return ans-*min(mi[x][k],mi[y-(<<k)+][k]);
}
int CG,f[maxn],size,siz[maxn],fa[maxn];bool vis[maxn];
void findcg(int x,int fa){
siz[x]=;int mxs=;
for(ted*e=fch[x];e;e=e->nxt){
int v=e->y;if(v!=fa&&!vis[v]){
findcg(v,x);siz[x]+=siz[v];mxs=max(mxs,siz[v]);
}
}f[x]=max(mxs,size-siz[x]);if(f[x]<f[CG])CG=x;return;
}
void dfs(int x,int fa){
siz[x]=;
for(ted*e=fch[x];e;e=e->nxt){
int v=e->y;if(v!=fa&&!vis[v])dfs(v,x),siz[x]+=siz[v];
}return;
}
void solve(int x=CG){
vis[x]=true;
for(ted*e=fch[x];e;e=e->nxt){
int v=e->y;if(!vis[v]){
dfs(v,x);f[CG=]=size=siz[v];findcg(v,x);fa[CG]=x;solve();
}
}return;
}
void update(int x){
insert(tre[x],);
for(int ret=x;fa[x];x=fa[x]){
int d=dist(ret,fa[x]);
insert(tre[fa[x]],d);insert(cha[x],d);
}return;
}
int k;
int query(int x){
int ans=find(tre[x],k);
for(int ret=x;fa[x];x=fa[x]){
int d=dist(ret,fa[x]);
ans+=find(tre[fa[x]],k-d)-find(cha[x],k-d);
}return ans;
}
int n,L,R;
int cal(int t){
k=t+;int ans=;for(int i=;i<=n;i++)ans+=query(i);return ans;
}
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')sig=-;ch=getchar();}
while(isdigit(ch))x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(int x){
if(x==){putchar('');return;}if(x<)putchar('-'),x=-x;
int len=,buf[];while(x)buf[len++]=x%,x/=;
for(int i=len-;i>=;i--)putchar(buf[i]+'');return;
}
void init(){
srand(time());
n=read();L=read(),R=read();int x,y;
for(int i=;i<n;i++)x=read(),y=read(),add(x,y,read());build(,,);initrmq();
f[CG=]=size=n;findcg(,);solve();for(int i=;i<=n;i++)update(i);
write((cal(R)-cal(L-))>>);
return;
}
void work(){
return;
}
void print(){
return;
}
int main(){init();work();print();return ;}
COJ 0346 WZJ的旅行(二)更新动态树分治版本的更多相关文章
- 点分治Day2 动态树分治
蒟蒻Ez3real冬令营爆炸之后滚回来更新blog... 我们看一道题 bzoj3924 ZJOI2015D1T1 幻想乡战略游戏 给一棵$n$个点的树$(n \leqslant 150000)$ 点 ...
- 洛谷P4719 【模板】"动态 DP"&动态树分治
[模板]"动态 DP"&动态树分治 第一道动态\(DP\)的题,只会用树剖来做,全局平衡二叉树什么的就以后再学吧 所谓动态\(DP\),就是在原本的\(DP\)求解的问题上 ...
- 【Learning】 动态树分治
简介 动态树分治整体上由点分治发展而来. 点分治是统计树上路径,而动态树分治用来统计与点有关的树上路径,比如多次询问某一些点到询问点的距离和. 前置知识就是点分治. 做法 众所周知,点分树(点分治中重 ...
- 【xsy2818】 最近点 动态树分治+可持久化线段树
题目大意:给你一颗n个节点的树,最初点集S为空. 有m次操作:往当前点集S中加入/删除一个点,询问点x至集合S中任意点的最小距离,回到第t次修改点集的操作后的状态. 数据范围:$n,m≤10^5$ 我 ...
- 【BZOJ3730】震波 动态树分治+线段树
[BZOJ3730]震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i].不幸的是,这片土 ...
- COJ 0349 WZJ的旅行(五)
WZJ的旅行(五) 难度级别:E: 运行时间限制:3000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 WZJ又要去旅行了T^T=0.幻想国由N个城市组成,由于道 ...
- 【BZOJ1095】[ZJOI2007]Hide 捉迷藏 动态树分治+堆
[BZOJ1095][ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉 ...
- 【BZOJ4372】烁烁的游戏 动态树分治+线段树
[BZOJ4372]烁烁的游戏 Description 背景:烁烁很喜欢爬树,这吓坏了树上的皮皮鼠.题意:给定一颗n个节点的树,边权均为1,初始树上没有皮皮鼠.烁烁他每次会跳到一个节点u,把周围与他距 ...
- 【BZOJ4317】Atm的树 动态树分治+二分+线段树
[BZOJ4317]Atm的树 Description Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径 ...
随机推荐
- Android 根据屏幕分辨率自动调整字体大小
1.在oncreate 里获取手机屏幕宽和高度 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDispl ...
- 10.6 noip模拟试题
更正:第三组:不存在相同的字符|str|=26,26<=n<=100 60 /* 呵呵哒~这题 正解还在研究.... 因为没有题解只有个std还在看 不过乱搞一下可以70(数据好像有问题只 ...
- codevs 2822爱在心中
不想吐槽题目.... /* K bulabula 算法(好像用哪个T bulabula更简单 然而我并不会 - -) 丑陋的处理cnt: Printf时 cnt中 ans[i][0]==1 的删掉 然 ...
- discuz论坛几种安全策略(一)
安全问题 最近公司准备搭建一个discuz论坛,大头让我调研一下discuz的安全策略,并提出如下几点要求: 1.防止php上传漏洞2.防止大量刷新攻击限制某个IP大量刷新某一页面导致论坛宕机3.防止 ...
- jetty运行maven程序(修改及时生效,不需要重启jetty程序)
jetty:run -Djetty:port=9999
- HTML5 文件域+FileReader 分段读取文件并上传到服务器(六)
说明:使用Ajax方式上传,文件不能过大,最好小于三四百兆,因为过多的连续Ajax请求会使后台崩溃,获取InputStream中数据会为空,尤其在Google浏览器测试过程中. 1.简单分段读取文件为 ...
- PictureBox内的图片拖动功能
当 PictureBox内的图片太大,超过PictureBox边框时可以用下面的方法来实现, 通过重绘来实现 : Code bool wselected = false; Point p = ...
- Servlet(三)
重定向 服务器向浏览器发送一个302状态码以及一个Location消息头(该消息头的值是一个地址,称之为重定向地址),浏览器收到后会立即向重定向的地址发出请求,使用相应对象的API方法实现(respo ...
- linux负载均衡
1.linux lvs nat实现负载均衡 添加两块网卡并开启路由管道 > /proc/sys/net/ipv4/ip_forward //开始路由管道 安装ipvsadm yum instal ...
- Zend Server安装后首次运行就出现Internal Server Error的解决(转)
新近学习php,结果装了Zend Server上来就报错,网上找到了解决方法,照着做果然可行,转之. 刚才安装了Zend Server,安装后首次运行就爆出了一个Internal Server Err ...