POJ 2763
来源:互联网 发布:总裁小说改编的网络剧 编辑:程序博客网 时间:2024/06/01 10:19
题意:给定一棵含n个结点的树,共有q次操作,分为两种
0 c :求从位置s到c的距离,然后s变成c
1 a b:把第a条边的权值变为b
n<10w,q<10w
题解:求树中两点距离显然是LCA,关于对原树中边权的修改,假设改了(a,b)使得其边增大了c,那么如果a是b的父亲,那么以b为子树的所有结点到根的距离都将增加c。求解LCA可以得到dfs序列,记录下每个结点初始访问时间以及最后访问时间,那么如果以该节点为子树的结点距根节点距离有变,只需对这个区间内每个值加上c即可,线段树可以做,但太麻烦了,实际上可以用树状数组直接在这区间头加上c,区间尾后面减去c,然后求值时受影响的就只有这个区间了。
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int N = 400005; // 1<<20;int prt[N],pnt[N], next[N], head[N],cost[N]; // 邻接表bool visited[N]; // 初始为0,从根遍历int e,id;int dep[N], E[N], R[N],ED[N],fa[N],dist[N]; // dep:dfs遍历节点深度, E:dfs序列, R:第一次被遍历的下标void DFS(int u, int d);int d[40], st[N][40];int ar[N]; // index: 1 ~ Nint lowb(int t){ return t&(-t) ;}void add(int i, int v){ for ( ; i < N; ar[i] += v, i += lowb(i));}int sum(int i){ int s = 0; for ( ; i > 0; s += ar[i], i -= lowb(i)); return s;}int Query(int x, int y){ int k; k = int( log(double(y-x+1))/log(2.0) ); return dep[ st[x][k] ] > dep[ st[y-d[k]+1][k] ] ? st[y-d[k]+1][k] : st[x][k];}int LCA(int x,int y){ if( x > y ) swap(x,y); return E[Query(x, y)];}void DFS(int u, int d,int dis){ visited[u] = 1; R[u] = id; E[id] = u; dist[u]=dis; dep[id++] = d; for( int i=head[u]; i != -1; i=next[i] ) if( visited[ pnt[i] ] == 0 ) { fa[pnt[i]]=u; DFS(pnt[i], d+1,cost[i]+dis); E[id] = u; dep[id++] = d; } ED[u]=id;}void InitRMQ(){ int i, j; for( d[0]=1, i=1; i < 20; ++i ) d[i] = 2*d[i-1]; for( i=0; i < id; ++i ) st[i][0] = i; int k = int( log(double(N))/log(2.0) ) + 1; for( j=1; j < k; ++j ) for( i=0; i < id; ++i ) if( i+d[j-1]-1 < id ) st[i][j]=dep[st[i][j-1]]>dep[ st[i+d[j-1]][j-1]]?st[i+d[j-1]][j-1]:st[i][j-1]; else break;}void addedge(int a,int b,int c){ prt[e]=a;pnt[e]=b;next[e]=head[a];cost[e]=c;head[a]=e++; prt[e]=b;pnt[e]=a;next[e]=head[b];cost[e]=c;head[b]=e++;}struct Edge{ int a,b,c; Edge(){} Edge(int _a,int _b,int _c) { a=_a,b=_b,c=_c; }}EE[N];int main(){ int n,q,s,a,b,c,op,x,y,z; while(scanf("%d%d%d",&n,&q,&s)!=EOF) { memset(head,-1,sizeof(head)); memset(ar,0,sizeof(ar)); memset(visited,0,sizeof(visited)); id=e=0; for(int i=1;i<n;i++) { scanf("%d%d%d",&a,&b,&c); EE[i]=Edge(a,b,c); addedge(a,b,c); } DFS(s,0,0); fa[s]=s; InitRMQ(); for(int i=0;i<q;i++) { scanf("%d",&op); if(op==0) { scanf("%d",&b); x=R[s];y=R[b];z=R[c=LCA(x,y)]; printf("%d\n",sum(x+1)+sum(y+1)-2*sum(z+1)+dist[s]+dist[b]-2*dist[c]); s=b; } else { scanf("%d%d",&a,&c); x=EE[a].a; y=EE[a].b; int tp=c-EE[a].c; EE[a].c=c; if(fa[x]==y) swap(x,y); add(R[y]+1,tp); add(ED[y]+1,-tp); } } } return 0;}
- POJ 2763
- POJ 2763
- POJ 2763 Housewife Wind
- 树链剖分入门 poj 2763
- POJ 2763 Housewife Wind
- poj 2763 Housewife Wind
- poj 2763树链剖分
- POJ 2763 在线lca
- poj 2763(树链剖分)
- POJ 2763 Housewife Wind
- POJ 2763 树链剖分
- POJ 2763 Housewife Wind
- POJ 2763 LCA+BIT
- poj 2763 Housewife Wind
- POJ 2763 Housewife Wind
- POJ 2763 Housewife Wind
- poj 2763 LCA
- POJ 2763 Housewife Wind
- Chromium
- 大家一起写操作系统-准备知识(1)--计算机的启动过程
- 精明的程序员——小程大爱
- 杭电OJ题 1412 {A} + {B} 解题报告
- 多态性
- POJ 2763
- GNU C 的复合语句
- windows下技术
- VS2010下配置Opencv2.4.3
- net.sf.jasperreports.engine.util.JRFontNotFoundException: Font ‘黑体’ is not available to the JVM
- sqlite3 的常用指令
- Android开发--PreferenceActivity中打开子PreferenceScreen黑屏的解决办法
- onvif规范 中文介绍
- Qt 5简介