码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3966 dfs序+LCA+树状数组

时间:2014-09-30 18:08:09      阅读:374      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   os   ar   for   数据   sp   

题目意思很明白:

给你一棵有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 }

 

HDU 3966 dfs序+LCA+树状数组

标签:style   blog   color   io   os   ar   for   数据   sp   

原文地址:http://www.cnblogs.com/loloveping/p/4002156.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!