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

几道树剖模板题

时间:2016-02-20 22:59:53      阅读:442      评论:0      收藏:0      [点我收藏+]

标签:

寒假后半段一直都在外出旅游。。颓了好久。。qaq

旅游期间写了几道树剖模板题,贴上来。。

 

BZOJ 1036 没啥好说的,裸题

技术分享
  1 #include <cstdio>
  2 #include <algorithm>
  3 
  4 #define LEFT (segt[cur].l)
  5 #define RIGHT (segt[cur].r)
  6 #define MID (segt[cur].mid)
  7 #define SUM (segt[cur].Sum)
  8 #define MAX (segt[cur].Max)
  9 #define LCH (cur << 1)
 10 #define RCH ((cur << 1) | 1)
 11 
 12 using namespace std;
 13 
 14 void Get_Val(int &Ret)
 15 {
 16     Ret = 0;
 17     char ch;
 18     bool neg(false);
 19     while (ch = getchar(), (ch > 9 || ch < 0) && ch != -)
 20         ;
 21     if (ch == -)
 22     {
 23         neg = true;
 24         while (ch = getchar(), ch > 9 || ch < 0)
 25             ;
 26     }
 27     do
 28     {
 29         (Ret *= 10) += ch - 0;
 30     }
 31     while (ch = getchar(), ch >= 0 && ch <= 9);
 32     Ret = (neg ? -Ret : Ret);
 33 }
 34 
 35 const int Max_N(30050);
 36 const int root(1);
 37 
 38 int N;
 39 int W[Max_N];
 40 int Total, Head[Max_N], To[Max_N << 1], Next[Max_N << 1];
 41 int Father[Max_N], Deep[Max_N], Size[Max_N], Son[Max_N], Top[Max_N], ID[Max_N];
 42 int Tot, Number[Max_N];
 43 
 44 struct node
 45 {
 46     int l, r, mid;
 47     int Sum, Max;
 48 };
 49 
 50 struct Segment_Tree
 51 {
 52     node segt[Max_N << 2];
 53     void Make_Tree(const int&, const int&, const int&);
 54     inline
 55     void pushup(const int &cur)
 56     {
 57         MAX = max(segt[LCH].Max, segt[RCH].Max);
 58         SUM = segt[LCH].Sum + segt[RCH].Sum;
 59     }
 60     void Change(const int&, const int&, const int&);
 61     int RMQ_Max(const int&, const int&, const int&);
 62     int Query_Sum(const int&, const int&, const int&);
 63 };
 64 Segment_Tree Tree;
 65 
 66 void Segment_Tree::Make_Tree(const int &cur, const int &l, const int &r)
 67 {
 68     LEFT = l, RIGHT = r, MID = l + ((r - l) >> 1), SUM = 0, MAX = 0;
 69     if (l == r)
 70     {
 71         SUM = MAX = W[ID[l]];
 72         return;
 73     }
 74     Make_Tree(LCH, l, MID);
 75     Make_Tree(RCH, MID + 1, r);
 76     pushup(cur);
 77 }
 78 
 79 void Segment_Tree::Change(const int &cur, const int &i, const int &x)
 80 {
 81     if (LEFT == i && RIGHT == i)
 82     {
 83         SUM = MAX = x;
 84         return;
 85     }
 86     if (i <= MID)
 87         Change(LCH, i, x);
 88     else
 89         Change(RCH, i, x);
 90     pushup(cur);
 91 }
 92 
 93 int Segment_Tree::RMQ_Max(const int &cur, const int &l, const int &r)
 94 {
 95     if (l == LEFT && r == RIGHT)
 96         return MAX;
 97     if (r <= MID)
 98         return RMQ_Max(LCH, l, r);
 99     else
100         if (l > MID)
101             return RMQ_Max(RCH, l, r);
102         else
103             return max(RMQ_Max(LCH, l, MID), RMQ_Max(RCH, MID + 1, r));
104 }
105 
106 int Segment_Tree::Query_Sum(const int &cur, const int &l, const int &r)
107 {
108     if (l == LEFT && r == RIGHT)
109         return SUM;
110     if (r <= MID)
111         return Query_Sum(LCH, l, r);
112     else
113         if (l > MID)
114             return Query_Sum(RCH, l, r);
115         else
116             return Query_Sum(LCH, l, MID) + Query_Sum(RCH, MID + 1, r);
117 }
118 
119 inline
120 void Add_Edge(const int &s, const int &t)
121 {
122     ++Total;
123     To[Total] = t;
124     Next[Total] = Head[s], Head[s] = Total;
125 }
126 
127 void dfs1(const int &u, const int &fa)
128 {
129     Size[u] = 1;
130     int v;
131     for (int i = Head[u];i;i = Next[i])
132     {
133         v = To[i];
134         if (v != fa)
135         {
136             Father[v] = u, Deep[v] = Deep[u] + 1;
137             dfs1(v, u);
138             Size[u] += Size[v];
139             if (Size[v] > Size[Son[u]])
140                 Son[u] = v;
141         }
142     }
143 }
144 
145 void dfs2(const int &u, const int &fa)
146 {
147     Number[u] = ++Tot, ID[Tot] = u;
148     int v;
149     if (v = Son[u])
150     {
151         Top[v] = Top[u];
152         dfs2(v, u);
153     }
154     for (int i = Head[u];i;i = Next[i])
155     {
156         v = To[i];
157         if (v != fa && v != Son[u])
158         {
159             Top[v] = v;
160             dfs2(v, u);
161         }
162     }
163 }
164 
165 void init()
166 {
167     int a, b;
168     Get_Val(N);
169     for (int i = 1;i != N;++i)
170     {
171         Get_Val(a), Get_Val(b);
172         Add_Edge(a, b), Add_Edge(b, a);
173     }
174     for (int i = 1;i <= N;++i)
175         Get_Val(W[i]);
176     Deep[root] = 1, dfs1(root, Father[root] = -1);
177     Top[root] = root, dfs2(root, -1);
178 }
179 
180 int Query_Max(int u, int v)
181 {
182     int Max(-0X7F7F7F7F);
183     int r1(Top[u]), r2(Top[v]);
184     while (r1 != r2)
185     {
186         if (Deep[r1] < Deep[r2])
187             swap(u, v), swap(r1, r2);
188         Max = max(Max, Tree.RMQ_Max(1, Number[r1], Number[u]));
189         u = Father[r1];
190         r1 = Top[u];
191     }
192     if (Deep[u] > Deep[v])
193         swap(u, v);
194     return max(Max, Tree.RMQ_Max(1, Number[u], Number[v]));
195 }
196 
197 int Query_Sum(int u, int v)
198 {
199     int Sum(0);
200     int r1(Top[u]), r2(Top[v]);
201     while (r1 != r2)
202     {
203         if (Deep[r1] < Deep[r2])
204             swap(u, v), swap(r1, r2);
205         Sum += Tree.Query_Sum(1, Number[r1], Number[u]);
206         u = Father[r1];
207         r1 = Top[u];
208     }
209     if (Deep[u] > Deep[v])
210         swap(u, v);
211     return Sum + Tree.Query_Sum(1, Number[u], Number[v]);
212 }
213 
214 void work()
215 {
216     Tree.Make_Tree(1, 1, N);
217     int Q, u, v;
218     char op[10];
219     Get_Val(Q);
220     while (Q--)
221     {
222         scanf("%s", op), Get_Val(u), Get_Val(v);
223         if (*op == C)
224             Tree.Change(1, Number[u], v);
225         else
226             if (op[1] == M)
227                 printf("%d\n", Query_Max(u, v));
228             else
229                 printf("%d\n", Query_Sum(u, v));
230     }
231 }
232 
233 int main()
234 {
235     init();
236     work();
237     return 0;
238 }
BZOJ 1036

 

BZOJ 2157 边权转点权。。点权表示的是这个点到它父亲的边的权值,根节点的点权设置为无意义的值,比如和是0,最大值是-INF,最小值是INF。树剖修改查询的时候,只需要最后一步提升时,将两个点的lca无视即可。具体看代码。。写了7kbqaq

技术分享
  1 #include <cstdio>
  2 #include <algorithm>
  3 #define LEFT  (segt[cur].l)
  4 #define RIGHT (segt[cur].r)
  5 #define MID   (segt[cur].mid)
  6 #define SUM   (segt[cur].Sum)
  7 #define MAX   (segt[cur].Max)
  8 #define MIN   (segt[cur].Min)
  9 #define TAG   (segt[cur].Tag)
 10 #define LCH   (cur << 1)
 11 #define RCH   ((cur << 1) | 1)
 12 
 13 using namespace std;
 14 
 15 void Get_Val(int &Ret)
 16 {
 17     Ret = 0;
 18     char ch;
 19     bool neg(false);
 20     while (ch = getchar(), (ch > 9 || ch < 0) && ch != -)
 21         ;
 22     if (ch == -)
 23     {
 24         neg = true;
 25         while (ch = getchar(), ch > 9 || ch < 0)
 26             ;
 27     }
 28     do
 29     {
 30         (Ret *= 10) += ch -0;
 31     }
 32     while (ch = getchar(), ch >= 0 && ch <= 9);
 33     if (neg)
 34         Ret = -Ret;
 35 }
 36 
 37 const int Max_N(20050);
 38 const int root(1);
 39 const int INF(0X3F3F3F3F);
 40 
 41 struct edge
 42 {
 43     int u, v;
 44 };
 45 edge Edges[Max_N];
 46 
 47 int N;
 48 int Total, Head[Max_N], To[Max_N << 1], Next[Max_N << 1], Weight[Max_N << 1];
 49 int Father[Max_N], Cost[Max_N], Deep[Max_N], Size[Max_N], Son[Max_N], Top[Max_N];
 50 int Dfs_Clock, Pre[Max_N], ID[Max_N];
 51 
 52 inline
 53 void Add_Edge(const int &s, const int &t, const int &w)
 54 {
 55     ++Total;
 56     To[Total] = t, Weight[Total] = w;
 57     Next[Total] = Head[s], Head[s] = Total;
 58 }
 59 
 60 struct node
 61 {
 62     int l, r, mid;
 63     int Sum, Max, Min;
 64     bool Tag;
 65 };
 66 
 67 struct Segment_Tree
 68 {
 69     node segt[Max_N << 2];
 70     void build_tree(const int&, const int&, const int&);
 71     inline
 72     void pushup(const int &cur)
 73     {
 74         SUM = segt[LCH].Sum + segt[RCH].Sum;
 75         MAX = max(segt[LCH].Max, segt[RCH].Max), MIN = min(segt[LCH].Min, segt[RCH].Min);
 76     }
 77     inline
 78     void pushdown(const int &cur)
 79     {
 80         if (TAG)
 81         {
 82             segt[LCH].Sum = -segt[LCH].Sum;
 83             segt[RCH].Sum = -segt[RCH].Sum;
 84             swap((segt[LCH].Max = -segt[LCH].Max), (segt[LCH].Min = -segt[LCH].Min));
 85             swap((segt[RCH].Max = -segt[RCH].Max), (segt[RCH].Min = -segt[RCH].Min));
 86             segt[LCH].Tag = !segt[LCH].Tag, segt[RCH].Tag = !segt[RCH].Tag;
 87             TAG = false;
 88         }
 89     }
 90     void change(const int&, const int&, const int&);
 91     void opposite(const int&, const int&, const int&);
 92     int Sum(const int&, const int&, const int&);
 93     int Min(const int&, const int&, const int&);
 94     int Max(const int&, const int&, const int&);
 95 };
 96 Segment_Tree Tree;
 97 
 98 void Segment_Tree::build_tree(const int &cur, const int &l, const int &r)
 99 {
100     LEFT = l, RIGHT = r, MID = l + ((r - l) >> 1), TAG = false;
101     if (l == r)
102     {
103         if (ID[l] == root)
104             MAX = -INF, MIN = INF, SUM = 0;
105         else
106             MAX = MIN = SUM = Cost[ID[l]];
107         return;
108     }
109     build_tree(LCH, l, MID), build_tree(RCH, MID + 1, r);
110     pushup(cur);
111 }
112 
113 void Segment_Tree::change(const int &cur, const int &i, const int &x)
114 {
115     if (LEFT == i && RIGHT == i)
116     {
117         SUM = MAX = MIN = x;
118         return;
119     }
120     pushdown(cur);
121     if (i <= MID)
122         change(LCH, i, x);
123     else
124         change(RCH, i, x);
125     pushup(cur);
126 }
127 
128 void Segment_Tree::opposite(const int &cur, const int &l, const int &r)
129 {
130     if (LEFT == l && RIGHT == r)
131     {
132         SUM = -SUM;
133         swap((MAX = -MAX), (MIN = -MIN));
134         TAG = !TAG;
135         return;
136     }
137     pushdown(cur);
138     if (r <= MID)
139         opposite(LCH, l, r);
140     else
141         if (l > MID)
142             opposite(RCH, l, r);
143         else
144         {
145             opposite(LCH, l, MID);
146             opposite(RCH, MID + 1, r);
147         }
148     pushup(cur);
149 }
150 
151 int Segment_Tree::Sum(const int &cur, const int &l, const int &r)
152 {
153     if (LEFT == l && RIGHT == r)
154         return SUM;
155     pushdown(cur);
156     if (r <= MID)
157         return Sum(LCH, l, r);
158     else
159         if (l > MID)
160             return Sum(RCH, l, r);
161         else
162             return Sum(LCH, l, MID) + Sum(RCH, MID + 1, r);
163 }
164 
165 int Segment_Tree::Max(const int &cur, const int &l, const int &r)
166 {
167     if (LEFT == l && RIGHT == r)
168         return MAX;
169     pushdown(cur);
170     if (r <= MID)
171         return Max(LCH, l, r);
172     else
173         if (l > MID)
174             return Max(RCH, l, r);
175         else
176             return max(Max(LCH, l, MID), Max(RCH, MID + 1, r));
177 }
178 
179 int Segment_Tree::Min(const int &cur, const int &l, const int &r)
180 {
181     if (LEFT == l && RIGHT == r)
182         return MIN;
183     pushdown(cur);
184     if (r <= MID)
185         return Min(LCH, l, r);
186     else
187         if (l > MID)
188             return Min(RCH, l, r);
189         else
190             return min(Min(LCH, l, MID), Min(RCH, MID + 1, r));
191 }
192 
193 void Opposite(int u, int v)
194 {
195     int r1(Top[u]), r2(Top[v]);
196     while (r1 != r2)
197     {
198         if (Deep[r1] < Deep[r2])
199             swap(u, v), swap(r1, r2);
200         Tree.opposite(1, Pre[r1], Pre[u]);
201         u = Father[r1], r1 = Top[u];
202     }
203     if (Deep[u] > Deep[v])
204         swap(u, v);
205     if (Pre[u] + 1 <= Pre[v])
206         Tree.opposite(1, Pre[u] + 1, Pre[v]);
207 }
208 
209 int Query_Sum(int u, int v)
210 {
211     int Ans(0), r1(Top[u]), r2(Top[v]);
212     while (r1 != r2)
213     {
214         if (Deep[r1] < Deep[r2])
215             swap(u, v), swap(r1, r2);
216         Ans += Tree.Sum(1, Pre[r1], Pre[u]);
217         u = Father[r1], r1 = Top[u];
218     }
219     if (Deep[u] > Deep[v])
220         swap(u, v);
221     if (Pre[u] + 1 <= Pre[v])
222         Ans += Tree.Sum(1, Pre[u] + 1, Pre[v]);
223     return Ans;
224 }
225 
226 int Query_Max(int u, int v)
227 {
228     int Ans(-INF), r1(Top[u]), r2(Top[v]);
229     while (r1 != r2)
230     {
231         if (Deep[r1] < Deep[r2])
232             swap(u, v), swap(r1, r2);
233         Ans = max(Ans, Tree.Max(1, Pre[r1], Pre[u]));
234         u = Father[r1], r1 = Top[u];
235     }
236     if (Deep[u] > Deep[v])
237         swap(u, v);
238     if (Pre[u] + 1 <= Pre[v])
239         Ans = max(Ans, Tree.Max(1, Pre[u] + 1, Pre[v]));
240     return Ans;
241 }
242 
243 int Query_Min(int u, int v)
244 {
245     int Ans(INF), r1(Top[u]), r2(Top[v]);
246     while (r1 != r2)
247     {
248         if (Deep[r1] < Deep[r2])
249             swap(u, v), swap(r1, r2);
250         Ans = min(Ans, Tree.Min(1, Pre[r1], Pre[u]));
251         u = Father[r1], r1 = Top[u];
252     }
253     if (Deep[u] > Deep[v])
254         swap(u, v);
255     if (Pre[u] + 1 <= Pre[v])
256         Ans = min(Ans, Tree.Min(1, Pre[u] + 1, Pre[v]));
257     return Ans;
258 }
259 
260 void dfs1(const int &u, const int &fa)
261 {
262     int v;
263     Size[u] = 1;
264     for (int i = Head[u];i;i = Next[i])
265     {
266         v = To[i];
267         if (v != fa)
268         {
269             Father[v] = u, Deep[v] = Deep[u] + 1, Cost[v] = Weight[i];
270             dfs1(v, u);
271             Size[u] += Size[v];
272             if (Size[v] > Size[Son[u]])
273                 Son[u] = v;
274         }
275     }
276 }
277 
278 void dfs2(const int &u)
279 {
280     Pre[u] = ++Dfs_Clock, ID[Dfs_Clock] = u;
281     int v;
282     if (v = Son[u])
283     {
284         Top[v] = Top[u];
285         dfs2(v);
286     }
287     for (int i = Head[u];i;i = Next[i])
288     {
289         v = To[i];
290         if (v != Father[u] && v != Son[u])
291         {
292             Top[v] = v;
293             dfs2(v);
294         }
295     }
296 }
297 
298 void init()
299 {
300     int u, v, w;
301     Get_Val(N);
302     for (int i = 1;i != N;++i)
303     {
304         Get_Val(u), Get_Val(v), Get_Val(w), ++u, ++v;
305         Add_Edge(u, v, w), Add_Edge(v, u, w);
306         Edges[i].u = u, Edges[i].v = v;
307     }
308     Deep[root] = 1, dfs1(root, Father[root] = -1);
309     Top[root] = root, dfs2(root);
310 }
311 
312 void work()
313 {
314     int M, u, v;
315     char op[10];
316     Tree.build_tree(1, 1, N);
317     Get_Val(M);
318     while (M--)
319     {
320         scanf("%s", op), Get_Val(u), Get_Val(v);
321         if (*op == C)
322         {
323             if (Deep[Edges[u].u] < Deep[Edges[u].v])
324                 u = Edges[u].v;
325             else
326                 u = Edges[u].u;
327             Tree.change(1, Pre[u], v);
328         }
329         else
330             if (*op == N)
331                 ++u, ++v, Opposite(u, v);
332             else
333                 if (*op == S)
334                     ++u, ++v, printf("%d\n", Query_Sum(u, v));
335                 else
336                     if (op[1] == A)
337                         ++u, ++v, printf("%d\n", Query_Max(u, v));
338                     else
339                         ++u, ++v, printf("%d\n", Query_Min(u, v));
340     }
341 }
342 
343 int main()
344 {
345     init();
346     work();
347     return 0;
348 }
BZOJ 2157

 

BZOJ 2243 树剖+线段树区间合并,合并区间的时候还要判断左区间的右端点和右区间的左端点是否相同

技术分享
#include <cstdio>
#include <algorithm>
#define LEFT  (segt[cur].l)
#define RIGHT (segt[cur].r)
#define MID   (segt[cur].mid)
#define PIECE (segt[cur].piece)
#define LC    (segt[cur].lc)
#define RC    (segt[cur].rc)
#define TAG   (segt[cur].Tag)
#define LCH   (cur << 1)
#define RCH   ((cur << 1) | 1)

using namespace std;

void Get_Val(int &Ret)
{
    Ret = 0;
    char ch;
    while (ch = getchar(), ch > 9 || ch < 0)
        ;
    do
    {
        (Ret *= 10) += ch - 0;
    }
    while (ch = getchar(), ch >= 0 && ch <= 9);
}

const int Max_N(100050);
const int root(1);

int N, M;
int Colour[Max_N];
int Total, Head[Max_N], To[Max_N << 1], Next[Max_N << 1];
int Father[Max_N], Deep[Max_N], Size[Max_N], Son[Max_N], Top[Max_N];
int Tot, Pre[Max_N], ID[Max_N];

struct question
{
    question(const int &a = 0, const int &b = 0, const int &c = 0) : 
        piece(a), lc(b), rc(c) {}
    int piece, lc, rc;
};

struct node
{
    int l, r, mid;
    int piece;
    int lc, rc;
    int Tag;
};

struct Segment_Tree
{
    node segt[Max_N << 2];
    void build_tree(const int&, const int&, const int&);
    inline
    void pushup(const int &cur)
    {
        PIECE = segt[LCH].piece + segt[RCH].piece - (segt[LCH].rc == segt[RCH].lc);
        LC = segt[LCH].lc, RC = segt[RCH].rc;
    }
    inline
    void pushdown(const int &cur)
    {
        if (TAG != -1)
        {
            segt[LCH].piece = segt[RCH].piece = 1;
            segt[LCH].lc = segt[LCH].rc = segt[RCH].lc = segt[RCH].rc = TAG;
            segt[LCH].Tag = segt[RCH].Tag = TAG;
            TAG = -1;
        }
    }
    void Set(const int&, const int&, const int&, const int&);
    question Query(const int&, const int&, const int&);
};
Segment_Tree Tree;

void Segment_Tree::build_tree(const int &cur, const int &l, const int &r)
{
    LEFT = l, RIGHT = r, MID = l + ((r - l) >> 1), TAG = -1;
    if (l == r)
    {
        PIECE = 1;
        LC = RC = Colour[ID[l]];
        return;
    }
    build_tree(LCH, l, MID), build_tree(RCH, MID + 1, r);
    pushup(cur);
}

void Segment_Tree::Set(const int &cur, const int &l, const int &r, const int &col)
{
    if (l == LEFT && r == RIGHT)
    {
        PIECE = 1;
        LC = RC = TAG = col;
        return;
    }
    pushdown(cur);
    if (r <= MID)
        Set(LCH, l, r, col);
    else
        if (l > MID)
            Set(RCH, l, r, col);
        else
        {
            Set(LCH, l, MID, col);
            Set(RCH, MID + 1, r, col);
        }
    pushup(cur);
}

question Segment_Tree::Query(const int &cur, const int &l, const int &r)
{
    if (l == LEFT && r == RIGHT)
        return question(PIECE, LC, RC);
    pushdown(cur);
    if (r <= MID)
        return Query(LCH, l, r);
    else
        if (l > MID)
            return Query(RCH, l, r);
        else
        {
            question ltree, rtree;
            ltree = Query(LCH, l, MID), rtree = Query(RCH, MID + 1, r);
            return question(ltree.piece + rtree.piece - (ltree.rc == rtree.lc), ltree.lc, rtree.rc);
        }
}

inline
void Add_Edge(const int &s, const int &t)
{
    ++Total;
    To[Total] = t;
    Next[Total] = Head[s], Head[s] = Total;
}

void dfs1(const int &u, const int &fa)
{
    Size[u] = 1;
    int v;
    for (int i = Head[u];i;i = Next[i])
    {
        v = To[i];
        if (v != fa)
        {
            Father[v] = u, Deep[v] = Deep[u] + 1;
            dfs1(v, u);
            Size[u] += Size[v];
            if (Size[v] > Size[Son[u]])
                Son[u] = v;
        }
    }
}

void dfs2(const int &u)
{
    int v;
    Pre[u] = ++Tot, ID[Tot] = u;
    if (v = Son[u])
    {
        Top[v] = Top[u];
        dfs2(v);
    }
    for (int i = Head[u];i;i = Next[i])
    {
        v = To[i];
        if (v != Father[u] && v != Son[u])
        {
            Top[v] = v;
            dfs2(v);
        }
    }
}

void change(int u, int v, const int &c)
{
    int r1(Top[u]), r2(Top[v]);
    while (r1 != r2)
    {
        if (Deep[r1] < Deep[r2])
            swap(u, v), swap(r1, r2);
        Tree.Set(1, Pre[r1], Pre[u], c);
        u = Father[r1], r1 = Top[u];
    }
    if (Deep[u] > Deep[v])
        swap(u, v);
    Tree.Set(1, Pre[u], Pre[v], c);
}

int query(int u, int v)
{
    int last_u_l(-1), last_u_r(-1), last_v_l(-1), last_v_r(-1);
    int now_u_l, now_u_r;
    int r1(Top[u]), r2(Top[v]), Ans(0);
    question now;
    while (r1 != r2)
    {
        if (Deep[r1] < Deep[r2])
            swap(u, v), swap(r1, r2), swap(last_u_l, last_v_l), swap(last_u_r, last_v_r);
        now = Tree.Query(1, Pre[r1], Pre[u]);
        Ans += now.piece, now_u_l = now.lc, now_u_r = now.rc;
        Ans -= (now_u_r == last_u_l);
        last_u_l = now_u_l, last_u_r = now_u_r;
        u = Father[r1], r1 = Top[u];
    }
    if (Deep[u] > Deep[v])
        swap(u, v), swap(last_u_l, last_v_l), swap(last_u_r, last_v_r);
    now = Tree.Query(1, Pre[u], Pre[v]);
    Ans += now.piece, now_u_l = now.lc, now_u_r = now.rc;
    Ans -= (now_u_l == last_u_l) + (now_u_r == last_v_l);
    return Ans;
}

void init()
{
    int x, y;
    Get_Val(N), Get_Val(M);
    for (int i = 1;i <= N;++i)
        Get_Val(Colour[i]);
    for (int i = 1;i != N;++i)
    {
        Get_Val(x), Get_Val(y);
        Add_Edge(x, y), Add_Edge(y, x);
    }
    Deep[root] = 1, dfs1(root, Father[root] = -1);
    Top[root] = root, dfs2(root);
}

void work()
{
    char op[5];
    int a, b, c;
    Tree.build_tree(1, 1, N);
    while (M--)
    {
        scanf("%s", op);
        if (*op == C)
        {
            Get_Val(a), Get_Val(b), Get_Val(c);
            change(a, b, c);
        }
        else
        {
            Get_Val(a), Get_Val(b);
            printf("%d\n", query(a, b));
        }
    }
}

int main()
{
    init();
    work();
    return 0;
}
BZOJ 2243

 

BZOJ 4034 不说了,裸题

技术分享
  1 #include <cstdio>
  2 #include <algorithm>
  3 #define LEFT (segt[cur].l)
  4 #define RIGHT (segt[cur].r)
  5 #define MID (segt[cur].mid)
  6 #define SUM (segt[cur].Sum)
  7 #define TAG (segt[cur].Tag)
  8 #define LCH (cur << 1)
  9 #define RCH ((cur << 1) | 1)
 10 
 11 using namespace std;
 12 
 13 template<typename Type>
 14 void Get_Val(Type &Ret)
 15 {
 16     Ret = 0;
 17     char ch;
 18     bool Neg(false);
 19     while (ch = getchar(), (ch > 9 || ch < 0) && ch != -)
 20         ;
 21     if (ch == -)
 22     {
 23         Neg = true;
 24         while (ch = getchar(), ch > 9 || ch < 0)
 25             ;
 26     }
 27     do
 28     {
 29         (Ret *= 10) += ch - 0;
 30     }
 31     while (ch = getchar(), ch >= 0 && ch <= 9);
 32     Ret = (Neg ? -Ret : Ret);
 33 }
 34 
 35 const int Max_N(100050);
 36 const int root(1);
 37 
 38 int N, M;
 39 long long int W[Max_N];
 40 int Total, Head[Max_N], To[Max_N << 1], Next[Max_N << 1];
 41 int Dfs_Clock, Father[Max_N], Deep[Max_N], Size[Max_N], Son[Max_N], Top[Max_N], Pre[Max_N], Post[Max_N], ID[Max_N];
 42 
 43 inline
 44 void Add_Edge(const int &s, const int &t)
 45 {
 46     ++Total;
 47     To[Total] = t;
 48     Next[Total] = Head[s], Head[s] = Total;
 49 }
 50 
 51 struct node
 52 {
 53     int l, r, mid;
 54     long long int Sum, Tag;
 55 };
 56 
 57 struct Segment_Tree
 58 {
 59     node segt[Max_N << 2];
 60     void build_tree(const int&, const int&, const int&);
 61     inline
 62     void pushup(const int &cur)
 63     {
 64         SUM = segt[LCH].Sum + segt[RCH].Sum;
 65     }
 66     inline
 67     void pushdown(const int &cur)
 68     {
 69         if (TAG)
 70         {
 71             segt[LCH].Sum += (segt[LCH].r - segt[LCH].l + 1) * TAG;
 72             segt[RCH].Sum += (segt[RCH].r - segt[RCH].l + 1) * TAG;
 73             segt[LCH].Tag += TAG, segt[RCH].Tag += TAG;
 74             TAG = 0;
 75         }
 76     }
 77     void Add(const int&, const int&, const int&, const long long int&);
 78     long long int Sum(const int&, const int&, const int&);
 79 };
 80 Segment_Tree Tree;
 81 
 82 void Segment_Tree::build_tree(const int &cur, const int &l, const int &r)
 83 {
 84     LEFT = l, RIGHT = r, MID = l + ((r - l) >> 1), TAG = 0;
 85     if (l == r)
 86     {
 87         SUM = W[ID[l]];
 88         return;
 89     }
 90     build_tree(LCH, l, MID), build_tree(RCH, MID + 1, r);
 91     pushup(cur);
 92 }
 93 
 94 void Segment_Tree::Add(const int &cur, const int &l, const int &r, const long long int &x)
 95 {
 96     if (l == LEFT && r == RIGHT)
 97     {
 98         SUM += (RIGHT - LEFT + 1) * x;
 99         TAG += x;
100         return;
101     }
102     pushdown(cur);
103     if (r <= MID)
104         Add(LCH, l, r, x);
105     else
106         if (l > MID)
107             Add(RCH, l, r, x);
108         else
109             Add(LCH, l, MID, x), Add(RCH, MID + 1, r, x);
110     pushup(cur);
111 }
112 
113 long long int Segment_Tree::Sum(const int &cur, const int &l, const int &r)
114 {
115     if (l == LEFT && r == RIGHT)
116         return SUM;
117     pushdown(cur);
118     if (r <= MID)
119         return Sum(LCH, l, r);
120     else
121         if (l > MID)
122             return Sum(RCH, l, r);
123         else
124             return Sum(LCH, l, MID) + Sum(RCH, MID + 1, r);
125 }
126 
127 void dfs1(const int &u, const int &fa)
128 {
129     Size[u] = 1;
130     int v;
131     for (int i = Head[u];i;i = Next[i])
132     {
133         v = To[i];
134         if (v != fa)
135         {
136             Father[v] = u, Deep[v] = Deep[u] + 1;
137             dfs1(v, u);
138             Size[u] += Size[v];
139             if (Size[v] > Size[Son[u]])
140                 Son[u] = v;
141         }
142     }
143 }
144 
145 void dfs2(const int &u)
146 {
147     Pre[u] = Post[u] = ++Dfs_Clock, ID[Dfs_Clock] = u;
148     int v;
149     if (v = Son[u])
150     {
151         Top[v] = Top[u];
152         dfs2(v);
153         Post[u] = max(Post[u], Post[v]);
154     }
155     for (int i = Head[u];i;i = Next[i])
156     {
157         v = To[i];
158         if (v != Father[u] && v != Son[u])
159         {
160             Top[v] = v;
161             dfs2(v);
162             Post[u] = max(Post[u], Post[v]);
163         }
164     }
165 }
166 
167 void init()
168 {
169     Get_Val(N), Get_Val(M);
170     int fr, to;
171     for (int i = 1;i <= N;++i)
172         Get_Val(W[i]);
173     for (int i = 1;i != N;++i)
174     {
175         Get_Val(fr), Get_Val(to);
176         Add_Edge(fr, to), Add_Edge(to, fr);
177     }
178     Deep[root] = 1, dfs1(root, Father[root] = -1);
179     Top[root] = root, dfs2(root);
180 }
181 
182 long long int Query(int u, int v)
183 {
184     long long int Sum(0), r1(Top[u]), r2(Top[v]);
185     while (r1 != r2)
186     {
187         if (Deep[r1] < Deep[r2])
188             swap(u, v), swap(r1, r2);
189         Sum += Tree.Sum(1, Pre[r1], Pre[u]);
190         u = Father[r1], r1 = Top[u];
191     }
192     if (Deep[u] > Deep[v])
193         swap(u, v);
194     return Sum + Tree.Sum(1, Pre[u], Pre[v]);
195 }
196 
197 void work()
198 {
199     Tree.build_tree(1, 1, N);
200     int op, x, a;
201     while (M--)
202     {
203         Get_Val(op);
204         if (op == 1)
205         {
206             Get_Val(x), Get_Val(a);
207             Tree.Add(1, Pre[x], Pre[x], a);
208         }
209         if (op == 2)
210         {
211             Get_Val(x), Get_Val(a);
212             Tree.Add(1, Pre[x], Post[x], a);
213         }
214         if (op == 3)
215         {
216             Get_Val(x);
217             printf("%lld\n", Query(x, root));
218         }
219     }
220 }
221 
222 int main()
223 {
224     init();
225     work();
226     return 0;
227 }
BZOJ 4034

 

BZOJ 4196 裸题。。觉得noi考这种数据结构裸题很没有意思啊

技术分享
  1 #include <queue>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define LEFT  (segt[cur].l)
  6 #define RIGHT (segt[cur].r)
  7 #define MID   (segt[cur].mid)
  8 #define ZERO  (segt[cur].Sum[0])
  9 #define ONE   (segt[cur].Sum[1])
 10 #define TAG   (segt[cur].Tag)
 11 #define LCH   (cur << 1)
 12 #define RCH   ((cur << 1) | 1)
 13 
 14 using namespace std;
 15 
 16 const int Max_N(100050);
 17 const int root(1);
 18 
 19 void Get_Val(int &Ret)
 20 {
 21     Ret = 0;
 22     char ch;
 23     while (ch = getchar(), ch > 9 || ch < 0)
 24         ;
 25     do
 26     {
 27         (Ret *= 10) += ch - 0;
 28     }
 29     while (ch = getchar(), ch >= 0 && ch <= 9);
 30 }
 31 
 32 int N;
 33 int Total, Head[Max_N], To[Max_N], Next[Max_N];
 34 int Father[Max_N], Deep[Max_N], Size[Max_N], Son[Max_N], Top[Max_N];
 35 int Dfs_Clock, Pre[Max_N], Post[Max_N];
 36 int Degree[Max_N];
 37 
 38 struct node
 39 {
 40     int l, r, mid;
 41     int Sum[2], Tag;
 42 };
 43 
 44 struct Segment_Tree
 45 {
 46     node segt[Max_N << 2];
 47     void build_tree(const int&, const int&, const int&);
 48     inline
 49     void pushup(const int &cur)
 50     {
 51         ZERO = segt[LCH].Sum[0] + segt[RCH].Sum[0];
 52         ONE = segt[LCH].Sum[1] + segt[RCH].Sum[1];
 53     }
 54     inline
 55     void pushdown(const int &cur)
 56     {
 57         if (TAG != -1)
 58         {
 59             if (TAG)
 60             {
 61                 segt[LCH].Sum[1] = segt[LCH].r - segt[LCH].l + 1;
 62                 segt[RCH].Sum[1] = segt[RCH].r - segt[RCH].l + 1;
 63                 segt[LCH].Sum[0] = segt[RCH].Sum[0] = 0;
 64             }
 65             else
 66             {
 67                 segt[LCH].Sum[0] = segt[LCH].r - segt[LCH].l + 1;
 68                 segt[RCH].Sum[0] = segt[RCH].r - segt[RCH].l + 1;
 69                 segt[LCH].Sum[1] = segt[RCH].Sum[1] = 0;
 70             }
 71             segt[LCH].Tag = segt[RCH].Tag = TAG;
 72             TAG = -1;
 73         }
 74     }
 75     int Set(const int&, const int&, const int&, const int&);
 76 };
 77 Segment_Tree Tree;
 78 
 79 void Segment_Tree::build_tree(const int &cur, const int &l, const int &r)
 80 {
 81     LEFT = l, RIGHT = r, MID = l + ((r - l) >> 1);
 82     ONE = 0, ZERO = r - l + 1, TAG = -1;
 83     if (l == r)
 84         return;
 85     build_tree(LCH, l, MID), build_tree(RCH, MID + 1, r);
 86 }
 87 
 88 int Segment_Tree::Set(const int &cur, const int &l, const int &r, const int &x)
 89 {
 90     int Ans;
 91     if (l == LEFT && r == RIGHT)
 92     {
 93         Ans = segt[cur].Sum[1 - x];
 94         if (x)
 95             ONE = RIGHT - LEFT + 1, ZERO = 0;
 96         else
 97             ZERO = RIGHT - LEFT + 1, ONE = 0;
 98         TAG = x;
 99         return Ans;
100     }
101     pushdown(cur);
102     if (r <= MID)
103     {
104         Ans = Set(LCH, l, r, x);
105         pushup(cur);
106     }
107     else
108         if (l > MID)
109         {
110             Ans = Set(RCH, l, r, x);
111             pushup(cur);
112         }
113         else
114         {
115             Ans = Set(LCH, l, MID, x) + Set(RCH, MID + 1, r, x);
116             pushup(cur);
117         }
118     return Ans;
119 }
120 
121 inline
122 void Add_Edge(const int &s, const int &t)
123 {
124     ++Total;
125     To[Total] = t;
126     Next[Total] = Head[s], Head[s] = Total;
127 }
128 
129 void bfs1()
130 {
131     queue<int> Q;
132     int u, fa;
133     for (int i = 1;i <= N;++i)
134         if (!Degree[i])
135             Q.push(i);
136     while (Q.size())
137     {
138         u = Q.front(), Q.pop();
139         fa = Father[u];
140         ++Size[u];
141         if (u != root)
142         {
143             Size[fa] += Size[u];
144             if (Size[u] > Size[Son[fa]])
145                 Son[fa] = u;
146             Add_Edge(fa, u);
147             if ((--Degree[fa]) == 0)
148                 Q.push(fa);
149         }
150     }
151 }
152 
153 void dfs2(const int &u)
154 {
155     int v;
156     Pre[u] = Post[u] = ++Dfs_Clock;
157     if (v = Son[u])
158     {
159         Top[v] = Top[u];
160         Deep[v] = Deep[u] + 1;
161         dfs2(v);
162         Post[u] = Post[v];
163     }
164     for (int i = Head[u];i;i = Next[i])
165         if ((v = To[i]) != Son[u])
166         {
167             Top[v] = v;
168             Deep[v] = Deep[u] + 1;
169             dfs2(v);
170             Post[u] = Post[v];
171         }
172 }
173 
174 void init()
175 {
176     Get_Val(N);
177     for (int i = 2;i <= N;++i)
178         Get_Val(Father[i]), ++Father[i], ++Degree[Father[i]];
179     Father[root] = -1, bfs1();
180     Deep[root] = 1, Top[root] = root, dfs2(root);
181 }
182 
183 int Query(int u, int v)
184 {
185     int Ans(0), r1(Top[u]), r2(Top[v]);
186     while (r1 != r2)
187     {
188         if (Deep[r1] < Deep[r2])
189             swap(r1, r2), swap(u, v);
190         Ans += Tree.Set(1, Pre[r1], Pre[u], 1);
191         u = Father[r1], r1 = Top[u];
192     }
193     if (Deep[u] > Deep[v])
194         swap(u, v);
195     return Ans + Tree.Set(1, Pre[u], Pre[v], 1);
196 }
197 
198 void work()
199 {
200     int Q, x;
201     Get_Val(Q);
202     char op[20];
203     Tree.build_tree(1, 1, N);
204     while (Q--)
205     {
206         scanf("%s", op);
207         Get_Val(x);
208         ++x;
209         if (*op == i)
210             printf("%d\n", Query(x, root));
211         else
212             printf("%d\n", Tree.Set(1, Pre[x], Post[x], 0));
213     }
214 }
215 
216 int main()
217 {
218     init();
219     work();
220     return 0;
221 }
BZOJ 4196

 

几道树剖模板题

标签:

原文地址:http://www.cnblogs.com/Created-equal/p/5204153.html

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