传送门:Problem 3966

 https://www.cnblogs.com/violet-acmer/p/9711441.html

学习资料:

  [1]线段树区间更新:https://blog.csdn.net/zhhe0101/article/details/53871453

           https://yq.aliyun.com/articles/252586

  [2]树链剖分:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

         https://wenku.baidu.com/view/7548d8706ad97f192279168884868762caaebbfc.html?from=search

题意:

  敌军有N个营地,这N个营地通过M条边连接;
  每个营地有且仅有一条边连接(意味着M=N-1,就是一颗含有N个节点的树)
  要求支持两种操作:
  1营地u与营地v以及其之间的所有营地增加或减少ai个士兵。
  2询问营地u当前含有的士兵个数

题解:

  树链剖分模板题。

  实质上树链剖分进行了点对点的一次映射,保证了重链上的点在线段树上的位置是连续的。

  树链剖分的两个性质(转):

    性质1:如果(v,u)为轻边,则siz[u] * 2 < siz[v];

    性质2:从根到某一点的路径上轻链、重链的个数都不大于logn。

  保证了一个区间的时间复杂度是log2(n)。

  要分清3种标号含义(易混) :树中节点标号,树中节点对应线段树中位置标号,线段树中区间标号。

 

树链剖分相关数组意义 :

  siz[i] : 以i为根的子树的大小

  fa[i] : i节点的父亲

  depth[i]  : i节点的深度

  son[i] : i节点的重儿子(所有儿子中size最大的)

  tid[i] : i节点在线段树中对应的位置    

  top[i] : i节点所在重链的顶端节点,若为轻链,则为自身。

  rid[i] : 线段树中所对应树中节点(作用和tid[ ] 正好相反)。

AC代码:

  摘抄自大佬博客:

  分析:典型的树链剖分题目,先进行剖分,然后用线段树去维护即可,注意HDU的OJ采用Windows系统,容易爆栈,所以在代码前面加上:

  #pragma comment(linker, "/STACK:1024000000,1024000000")进行手动扩栈。

  (但不加也可以AC)

  1 //#pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 using namespace std;
  6 #define ls(x)((x)<<1)
  7 #define rs(x)((x)<<1 | 1)
  8 const int maxn=5e4+10;
  9 
 10 int A[maxn];
 11 //========链式前向星========
 12 struct Node1
 13 {
 14     int to;
 15     int next;
 16 }edge[maxn<<1];
 17 int head[maxn];
 18 int cnt;
 19 void addEdge(int u,int v)
 20 {
 21     edge[cnt].to=v;
 22     edge[cnt].next=head[u];
 23     head[u]=cnt++;
 24 }
 25 //==========================
 26 //=========树链剖分=========
 27 int fa[maxn];
 28 int son[maxn];
 29 int tid[maxn];
 30 int rid[maxn];
 31 int siz[maxn];
 32 int top[maxn];
 33 int depth[maxn];
 34 int label;
 35 
 36 void dfs1(int u,int f,int d)
 37 {
 38     fa[u]=f;
 39     siz[u]=1;
 40     depth[u]=d;
 41     for(int i=head[u];~i;i=edge[i].next)
 42     {
 43         int to=edge[i].to;
 44         if(to != f)
 45         {
 46             dfs1(to,u,d+1);
 47             siz[u] += siz[to];
 48             if(son[u] == -1 || siz[to] > siz[son[u]])
 49                 son[u]=to;
 50         }
 51     }
 52 }
 53 void dfs2(int u,int newTop)
 54 {
 55     top[u]=newTop;
 56     tid[u]=++label;
 57     rid[tid[u]]=u;
 58     if(son[u] == -1)
 59         return ;
 60     dfs2(son[u],newTop);
 61     for(int i=head[u];~i;i=edge[i].next)
 62     {
 63         int to=edge[i].to;
 64         if(to != son[u] && to != fa[u])
 65             dfs2(to,to);
 66     }
 67 }
 68 //==========================
 69 //==========线段树==========
 70 struct Node2
 71 {
 72     int l,r;
 73     int val;
 74     int lazy;
 75     int mid(){
 76         return l+((r-l)>>1);
 77     }
 78 }segTree[maxn<<2];
 79 void buildTree(int l,int r,int pos)
 80 {
 81     segTree[pos].l=l,segTree[pos].r=r;
 82     segTree[pos].lazy=0;
 83     if(l == r)
 84     {
 85         segTree[pos].val=A[rid[l]];
 86         return ;
 87     }
 88     int mid=l+((r-l)>>1);
 89     buildTree(l,mid,ls(pos));
 90     buildTree(mid+1,r,rs(pos));
 91 }
 92 void pushDown(int pos)
 93 {
 94 
 95     if(segTree[pos].lazy != 0)
 96     {
 97         segTree[ls(pos)].lazy += segTree[pos].lazy;
 98         segTree[rs(pos)].lazy += segTree[pos].lazy;
 99 
100         //segTree[ls(pos)].val += segTree[pos].lazy;
101         //segTree[rs(pos)].val += segTree[pos].lazy;
102 
103         segTree[pos].lazy=0;
104     }
105 }
106 void update(int a,int b,int val,int pos)
107 {
108     if(a <= segTree[pos].l && b >= segTree[pos].r)
109     {
110         segTree[pos].lazy += val;
111         //segTree[pos].val += val;
112         return ;
113     }
114     pushDown(pos);
115 
116     int mid=segTree[pos].mid();
117     if(b <= mid)
118         update(a,b,val,ls(pos));
119     else if(a > mid)
120         update(a,b,val,rs(pos));
121     else
122     {
123         update(a,mid,val,ls(pos));
124         update(mid+1,b,val,rs(pos));
125     }
126 }
127 int query(int k,int pos)
128 {
129     if(segTree[pos].l == segTree[pos].r)
130         return segTree[pos].val+segTree[pos].lazy;
131 
132     pushDown(pos);
133     int mid=segTree[pos].mid();
134 
135     if(k <= mid)
136         return query(k,ls(pos));
137     else
138         return query(k,rs(pos));
139 }
140 //==========================
141 void Find(int a,int b,int val)
142 {
143     while(top[a] != top[b])
144     {
145         if(depth[top[a]] > depth[top[b]])
146         {
147             update(tid[top[a]],tid[a],val,1);
148             a=fa[top[a]];
149         }
150         else
151         {
152             update(tid[top[b]],tid[b],val,1);
153             b=fa[top[b]];
154         }
155     }
156     if(tid[a] > tid[b])
157         swap(a,b);
158     update(tid[a],tid[b],val,1);
159 }
160 
161 void init()
162 {
163     cnt=0;
164     memset(head,-1,sizeof(head));
165     label=0;
166     memset(son,-1,sizeof(son));
167 }
168 int main()
169 {
170     int n,m,q;
171     while(~scanf("%d%d%d",&n,&m,&q))
172     {
173         init();
174         for(int i=1;i <= n;++i)
175             scanf("%d",A+i);
176         for(int i=1;i <= m;++i)
177         {
178             int u,v;
179             scanf("%d%d",&u,&v);
180             addEdge(u,v);
181             addEdge(v,u);
182         }
183         dfs1(1,1,0);
184         dfs2(1,1);
185         buildTree(1,label,1);
186         char op[3];
187         for(int i=1;i <= q;++i)
188         {
189             scanf("%s",op);
190             if(op[0] == 'Q')
191             {
192                 int c;
193                 scanf("%d",&c);
194                 printf("%d\n",query(tid[c],1));
195             }
196             else
197             {
198                 int c1,c2,k;
199                 scanf("%d%d%d",&c1,&c2,&k);
200                 if(op[0] == 'D')
201                     k = -k;
202                 Find(c1,c2,k);
203             }
204         }
205     }
206     return 0;
207 }
View Code

相关文章:

  • 2022-02-04
  • 2021-08-28
  • 2022-12-23
  • 2022-12-23
  • 2021-09-15
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-01-13
  • 2022-12-23
  • 2022-12-23
  • 2021-06-06
  • 2021-08-31
  • 2021-12-06
相关资源
相似解决方案