10.24T2 树链剖分
2.盟主的忧虑
(worry)
【问题描述】
江湖由 N 个门派(2≤N≤100,000,编号从 1 到 N)组成,这些门派之间有 N-1 条小道将他们连接起来,每条道路都以“尺”为单位去计量,武林盟主发现任何两个门派都能够直接或者间接通过小道连接。
虽然整个江湖是可以互相到达的,但是他担心有心怀不轨之徒破坏这个武林的安定,破坏小道,于是武林盟主又秘密地修建了 M 条密道(1≤M≤100,000),但每条小道距离都不超过10亿尺。
果不其然,最近一个名叫“太吾”的组织意欲破坏武林的小道,请你帮盟主想想办法,如果门派 A 到门派 B 的直连小道被破坏,从 A 走到 B 的所有路径中,经过密道的距离最少是多少?
【输入】
第一行数字 N M
接下来 N-1 行,每行两个整数 A B,表示 A-B 间有一条直连小道
接下来 M 行,每行三个数字 A B V,表示 A-B 间有一条代价为 V 的密道
【输出】
输出 N-1 行,对应原输入的小道,每个小道被破坏后,最少需要经过多长的密道?如果不存在替换的道路,请输出-1
【样例输入】
6 3
4 1
1 3
4 5
1 2
6 5
3 6 8
2 3 7
6 4 5
【样例输出】
8
7
5
7
5
【数据范围与约定】
30%数据:N<=300,M<=1000
50%数据:N<=1000,M<=1000
70%数据:N<=5000,M<=5000
对于另外15%的数据点:树是一条链
100%数据:N,M<=100,000
一条密道影响的是连接两点之间的简单路径,所以我们就可以用树链剖分覆盖两点之间的边,维护一下最小值就可以了,查询的时候所有边打包在一起查询就完成了
此题需要扩栈
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstdlib> 5 #define lc (p<<1) 6 #define rc (p<<1|1) 7 #define N 1000006 8 using namespace std; 9 const long long inf=99999999999; 10 struct node{ 11 long long u,v,w; 12 }e[N]; 13 struct NODE{ 14 int a,b,c; 15 }q[N]; 16 bool cmp(const NODE&a,const NODE&b){ 17 return a.c>b.c; 18 } 19 long long first[N],nxt[N],cnt,Ans[N]; 20 void add(long long u,long long v,long long w){ 21 e[++cnt].u=u; 22 e[cnt].v=v; 23 e[cnt].w=w; 24 nxt[cnt]=first[u]; 25 first[u]=cnt; 26 } 27 struct T{ 28 long long l,r,lazy; 29 }t[N]; 30 void pushnow(long long p,long long v){ 31 t[p].lazy=v; 32 } 33 void pushdown(long long p){ 34 if(t[p].lazy!=-1){ 35 pushnow(lc,t[p].lazy); 36 pushnow(rc,t[p].lazy); 37 t[p].lazy=-1; 38 } 39 } 40 void build(long long p,long long l,long long r){ 41 t[p].l=l,t[p].r=r;t[p].lazy=-1; 42 if(l==r)return; 43 long long mid=l+r>>1; 44 build(lc,l,mid); 45 build(rc,mid+1,r); 46 } 47 void update(long long p,long long ql,long long qr,long long v){ 48 if(ql<=t[p].l&&t[p].r<=qr){ 49 pushnow(p,v); 50 return; 51 } 52 pushdown(p); 53 long long mid=t[p].l+t[p].r>>1; 54 if(ql<=mid)update(lc,ql,qr,v); 55 if(qr>mid)update(rc,ql,qr,v); 56 } 57 long long siz[N],hson[N],dep[N],top[N],num[N],pre[N],tot,fa[N]; 58 void Count(long long p){ 59 if(t[p].l==t[p].r){ 60 Ans[pre[t[p].l]]=t[p].lazy; 61 return; 62 } 63 pushdown(p); 64 Count(lc); 65 Count(rc); 66 } 67 void dfs1(long long x,long long father){ 68 siz[x]=1,hson[x]=0;fa[x]=father; 69 for(long long i=first[x];i;i=nxt[i]){ 70 long long v=e[i].v; 71 if(v==father)continue; 72 dep[v]=dep[x]+1; 73 dfs1(v,x); 74 siz[x]+=siz[v]; 75 if(!hson[x]||siz[hson[x]]<siz[v])hson[x]=v; 76 } 77 } 78 void dfs2(long long x,long long tp,long long father){ 79 top[x]=tp; 80 pre[num[x]=++tot]=x; 81 if(hson[x])dfs2(hson[x],tp,x); 82 for(long long i=first[x];i;i=nxt[i]){ 83 long long v=e[i].v; 84 if(v==father)continue; 85 if(v==hson[x])continue; 86 dfs2(v,v,x); 87 } 88 } 89 long long modify(long long x,long long y,long long v){ 90 while(top[x]!=top[y]){ 91 if(dep[top[y]]>dep[top[x]])swap(x,y); 92 update(1,num[top[x]],num[x],v); 93 x=fa[top[x]]; 94 } 95 if(dep[x]<dep[y])swap(x,y); 96 if(num[y]+1<=num[x])update(1,num[y]+1,num[x],v); 97 } 98 int main(){ 99 int siz=100<<20;//40M 100 __asm__("movl %0,%%esp\n"::"r"((char*)malloc(siz)+siz));//windows用这个 101 //__asm__("movq %0,%%rsp\n"::"r"((char*)malloc(siz)+siz));//linux用这个 102 long long n,m; 103 cin>>n>>m; 104 for(long long i=1;i<n;i++){ 105 long long u,v; 106 cin>>u>>v; 107 add(u,v,0); 108 add(v,u,0); 109 } 110 fa[1]=1; 111 dfs1(1,1); 112 dfs2(1,1,1); 113 build(1,1,tot); 114 for(long long i=1;i<=m;i++){ 115 cin>>q[i].a>>q[i].b>>q[i].c; 116 } 117 sort(q+1,q+m+1,cmp); 118 for(int i=1;i<=m;i++){ 119 modify(q[i].a,q[i].b,q[i].c); 120 } 121 Count(1); 122 for(long long i=1;i<=cnt;i+=2){ 123 long long u=e[i].u,v=e[i].v; 124 if(fa[v]==u)swap(u,v); 125 printf("%d\n",Ans[u]); 126 } 127 exit(0); 128 return 0; 129 }
over