您的位置:首页 > 其它

BZOJ1602: [Usaco2008 Oct]牧场行走

2017-11-01 10:10 225 查看
Description

N头牛(2<=n<=1000)别人被标记为1到n,在同样被标记1到n的n块土地上吃草,第i头牛在第i块牧场吃草。 这n块土地被n-1条边连接。 奶牛可以在边上行走,第i条边连接第Ai,Bi块牧场,第i条边的长度是Li(1<=Li<=10000)。 这些边被安排成任意两头奶牛都可以通过这些边到达的情况,所以说这是一棵树。 这些奶牛是非常喜欢交际的,经常会去互相访问,他们想让你去帮助他们计算Q(1<=q<=1000)对奶牛之间的距离。

Input

*第一行:两个被空格隔开的整数:N和Q

*第二行到第n行:第i+1行有两个被空格隔开的整数:AI,BI,LI

*第n+1行到n+Q行:每一行有两个空格隔开的整数:P1,P2,表示两头奶牛的编号。

Output

*第1行到第Q行:每行输出一个数,表示那两头奶牛之间的距离。

Sample Input

4 2

2 1 2

4 3 2

1 4 3

1 2

3 2

Sample Output

2

7

题目传送门

LCA求最近公共祖先

然后。。。然后我就闲得无聊复习了一发树链剖分的模版

结果。。。



0ms的TLE,反正我没见过

再然后,我改小了数组

然后过了

PS:MLE就MLE啊,哪来的0MSTLE!

别像傻逼作者一样作死

代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct node{
int x,y,d,next;
}a[210000];int len,last[210000];
void ins(int x,int y,int d){
len++;
a[len].x=x;a[len].y=y;a[len].d=d;
a[len].next=last[x];last[x]=len;
}
struct trnode{
int l,r,lc,rc,c;
}tr[210000];int trlen;
void bt(int l,int r){
int now=++trlen;
tr[now].l=l;tr[now].r=r;tr[now].c=0;
tr[now].lc=tr[now].rc=-1;
if(l<r){
int mid=(l+r)/2;
tr[now].lc=trlen+1;bt(l,mid);
tr[now].rc=trlen+1;bt(mid+1,r);
}
}
int n,fa[210000],dep[210000],tot[210000],son[210000];
void pre_tree_node(int x){
son[x]=0;tot[x]=1;
for(int k=last[x];k;k=a[k].next){
int y=a[k].y;
if(y!=fa[x]){
fa[y]=x;
dep[y]=dep[x]+1;
pre_tree_node(y);
if(tot[son[x]]<tot[y])son[x]=y;
tot[x]+=tot[y];
}
}
}
int z,ys[210000],top[210000];
void pre_tree_edge(int x,int tp){
ys[x]=++z;top[x]=tp;
if(son[x]!=0)pre_tree_edge(son[x],tp);
for(int k=last[x];k;k=a[k].next){
int y=a[k].y;
if(y!=fa[x]&&y!=son[x])
pre_tree_edge(y,y);
}
}
void change(int now,int p,int c){
if(tr[now].l==tr[now].r){tr[now].c=c;return ;}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(p<=mid)change(lc,p,c);
else change(rc,p,c);
tr[now].c=tr[lc].c+tr[rc].c;
}
int findsum(int now,int l,int r){
if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(mid+1<=l)return findsum(rc,l,r);
else if(mid>=r)return findsum(lc,l,r);
else return findsum(lc,l,mid)+findsum(rc,mid+1,r);
}
int solve(int x,int y){
int tx=top[x],ty=top[y],ans=0;
while(tx!=ty){
if(dep[tx]>dep[ty]){
swap(x,y);
swap(tx,ty);
}
ans+=findsum(1,ys[ty],ys[y]);
y=fa[ty];ty=top[y];
}
if(x==y)return  ans;
else{
if(dep[x]>dep[y])swap(x,y);
return ans+findsum(1,ys[son[x]],ys[y]);
}
}
struct bian{
int x,y,c;
}e[510000];
int main(){
int m;
scanf("%d%d",&n,&m);
len=0;memset(last,0,sizeof(last));
for(int i=1;i<n;i++){
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].c);
ins(e[i].x,e[i].y,e[i].c);
ins(e[i].y,e[i].x,e[i].c);
}
dep[1]=0;fa[1]=0;pre_tree_node(1);
z=0;pre_tree_edge(1,1);
trlen=0;bt(1,z);
for(int i=1;i<n;i++){
if(dep[e[i].x]>dep[e[i].y])swap(e[i].x,e[i].y);
change(1,ys[e[i].y],e[i].c);
}
while(m--){

c69a
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",solve(x,y));
}
return 0;

}


by_lmy
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: