题目意思很明白:
给你一棵有n个节点的树,对树有下列操作:
I c1 c2 k 意思是把从c1节点到c2节点路径上的点权值加上k
D c1 c2 k 意思是把从c1节点到c2节点路径上的点权值减去k
Q a 查询节点a的权值
数据大小 节点个数 n[1,50000], 操作次数 op[0,30000];
不会树链剖分 故只有想其他的方法。
这道题有点类似今年上海网络赛的1003 ,不过那题我没做;
算法思路:
以节点1 为根,求出节点i 的 dfs序列 tim[i][2];
其中tim[i][0]存的是进入节点i的时间 ,tim[i][1]存的是离开节点i的时间
看操作: I a b k, 节点a到b的路径上所有点+k;最朴素的算法首先找到他们的最近公共祖先(LCA)(我用RMQ)写的;然后在路径上的每一个节点都+k;
假设树根是1
从a到树根的每一个节点x都满足tim[x][0]<=tim[a][0]<=tim[x][1];如此 如果引入一个数列nt,如果nt(tim[a][0])+=k,那么 nt数列从tim[x][0]到tim[x][1]项的和就加了k,这就相当于把从a到根节点的每一个节点的权值加上了k;
如果节点x不在a到根的路径上呢?那么只有可能是tim[x][0]>tim[a][0] or tim[x][1]<tim[a][0] 故上面的这种做法对其他的点没有影响
根据这种思路 ,那解法就相对简单了:
加上差分数列的思想
a b的LCA是t,把 a b节点都加上k,然后把t的父节点-2;当然 t节点是加了两遍的 所以需要减去一遍 也就是把t节点-1,父节点当然也要+1了
如果有了dfs序,就可以很清晰的看出来 如果一个节点x在这条路径上 那么tim[x][0]<=one of (tim[a][0],tim[b][0])<=tim[x][1];
附上代码渣渣:
1 // hdu 3966 2 #include<iostream> 3 #include<stdio.h> 4 #include<string.h> 5 #include <string> 6 #include <cmath> 7 #include <algorithm> 8 #include <map> 9 #include <set> 10 #include <queue> 11 #include <stack> 12 #include<stdlib.h> 13 #include <vector> 14 using namespace std; 15 16 #define ll __int64 17 #define CL(a,b) memset(a,b,sizeof(a)) 18 #define MAX_NODE 50010 19 20 int n,m,q; 21 22 int log_2(int x) 23 { 24 return (int)(log((double)x)/log(2.0)); 25 } 26 27 int tim[MAX_NODE][2],ti; 28 int rmq[MAX_NODE*2][30],cq,fv[MAX_NODE]; 29 int pre[MAX_NODE]; 30 int value[50010]; 31 32 typedef struct myedge 33 { 34 int v,next; 35 }E; 36 37 E edge[100010]; 38 int head[50010],ce; 39 40 void inithead() 41 { 42 CL(head,-1); 43 ce=0; 44 } 45 void addedge(int s,int e) 46 { 47 edge[ce].v=e;edge[ce].next=head[s];head[s]=ce++; 48 edge[ce].v=s;edge[ce].next=head[e];head[e]=ce++; 49 } 50 51 void initrmq() 52 { 53 int i,j; 54 for(j=1;(1<<j)<=cq;j++) 55 { 56 for(i=1;i+(1<<j)-1<=cq;i++) 57 { 58 rmq[i][j]=min(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1]); 59 } 60 } 61 } 62 int quermq(int s,int e) 63 { 64 int i=log_2(e-s+1); 65 return min(rmq[s][i],rmq[e-(1<<i)+1][i]); 66 } 67 68 ll nt[50010]; 69 70 int lowbit(int i) 71 { 72 return i&(-i); 73 } 74 75 void modify(int i,ll v) 76 { 77 if(i==0)return ; 78 for(i;i<=n;i+=lowbit(i)) 79 { 80 nt[i]+=v; 81 } 82 } 83 84 ll sum(int i) 85 { 86 ll rem=0; 87 for(i;i>0;i-=lowbit(i)) 88 rem+=nt[i]; 89 return rem; 90 } 91 92 int dfs(int i,int pr) 93 { 94 ti++; 95 tim[i][0]=ti; 96 // cout<<i<<" tim "<<ti<<endl; 97 rmq[++cq][0]=tim[i][0]; 98 fv[i]=cq; 99 pre[ti]=pr; 100 int p=head[i]; 101 while(p!=-1) 102 { 103 int v=edge[p].v; 104 if(tim[v][0]==0) 105 { 106 dfs(v,tim[i][0]); 107 rmq[++cq][0]=tim[i][0]; 108 } 109 p=edge[p].next; 110 } 111 tim[i][1]=ti; 112 return 0; 113 } 114 115 void inc(int s,int e,int k) 116 { 117 int rs=fv[s]; 118 int re=fv[e]; 119 int rt=quermq(min(rs,re),max(rs,re)); 120 re=tim[e][0]; 121 rs=tim[s][0]; 122 // cout<<rs<<‘ ‘<<re<<‘ ‘<<rt<<‘ ‘<<pre[rt]<<endl; 123 if(s==e) 124 { 125 value[s]+=k; 126 return ; 127 } 128 modify(rs,k); 129 modify(re,k); 130 modify(rt,-k); 131 modify(pre[rt],-k); 132 } 133 134 void dec(int s,int e,int k) 135 { 136 k=-k; 137 int rs=fv[s]; 138 int re=fv[e]; 139 int rt=quermq(min(rs,re),max(rs,re)); 140 re=tim[e][0]; 141 rs=tim[s][0]; 142 if(s==e) 143 { 144 value[s]+=k; 145 return ; 146 } 147 modify(rs,k); 148 modify(re,k); 149 modify(rt,-k); 150 modify(pre[rt],-k); 151 } 152 153 ll que(int k) 154 { 155 int rl=tim[k][0]; 156 int rr=tim[k][1]; 157 // cout<<rl<<‘ ‘<<rr<<endl; 158 return (ll)value[k]+sum(rr)-sum(rl-1); 159 } 160 161 char op[3]; 162 163 164 int main() 165 { 166 while(scanf("%d %d %d",&n,&m,&q)!=EOF) 167 { 168 CL(nt,0); 169 CL(rmq,0);cq=0; 170 CL(fv,0); 171 CL(pre,0); 172 CL(tim,0);ti=0; 173 inithead(); 174 int i,j,k; 175 int a,b,c; 176 for(i=1;i<=n;i++) 177 { 178 scanf("%d",value+i); 179 } 180 for(i=1;i<n;i++) 181 { 182 scanf("%d %d",&a,&b); 183 addedge(a,b); 184 } 185 dfs(1,0); 186 /* 187 for(i=1;i<=cq;i++) 188 { 189 printf("%d ",rmq[i][0]); 190 }cout<<endl; 191 */ 192 initrmq(); 193 for(i=0;i<q;i++) 194 { 195 scanf("%s",op); 196 if(op[0]==‘I‘) 197 { 198 scanf("%d %d %d",&a,&b,&c); 199 inc(a,b,c); 200 } 201 else if(op[0]==‘D‘) 202 { 203 scanf("%d %d %d",&a,&b,&c); 204 dec(a,b,c); 205 } 206 else if(op[0]==‘Q‘) 207 { 208 scanf("%d",&a); 209 printf("%I64d\n",que(a)); 210 } 211 } 212 213 } 214 215 return 0; 216 }