• POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)


    题目链接:http://poj.org/problem?id=3237

    一棵有边权的树,有3种操作。

    树链剖分+线段树lazy标记。lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每次更新异或1就可以。

    熟悉线段树成段更新就很简单了,最初姿势不对一直wa,还是没有彻底理解lazy标记啊。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 using namespace std;
      5 const int MAXN = 1e4 + 5;
      6 struct EDGE {
      7     int next , to , cost;
      8 }edge[MAXN << 1];
      9 int head[MAXN] , tot;
     10 int par[MAXN] , size[MAXN] , son[MAXN] , dep[MAXN];
     11 int top[MAXN] , id[MAXN] , cnt;
     12 int from[MAXN] , to[MAXN] , cost[MAXN];
     13 
     14 void init() {
     15     tot = cnt = 0;
     16     memset(head , -1 , sizeof(head));
     17 }
     18 
     19 inline void add(int u , int v , int cost) {
     20     edge[tot].next = head[u];
     21     edge[tot].to = v;
     22     head[u] = tot++;
     23 }
     24 
     25 void dfs1(int u , int p , int d) {
     26     par[u] = p , size[u] = 1 , son[u] = u , dep[u] = d;
     27     for(int i = head[u] ; ~i ; i = edge[i].next) {
     28         int v = edge[i].to;
     29         if(v == p)
     30             continue;
     31         dfs1(v , u , d + 1);
     32         if(size[v] >= size[son[u]])
     33             son[u] = v;
     34         size[u] += size[v];
     35     }
     36 }
     37 
     38 void dfs2(int u , int p , int t) {
     39     top[u] = t , id[u] = ++cnt;
     40     if(son[u] != u)
     41         dfs2(son[u] , u , t);
     42     for(int i = head[u] ; ~i ; i = edge[i].next) {
     43         int v = edge[i].to;
     44         if(v == p || v == son[u])
     45             continue;
     46         dfs2(v , u , v);
     47     }
     48 }
     49 
     50 struct SegTree {
     51     int l , r , Max , lazy , Min; //lazy变量0表示无更新 1表示有更新
     52 }T[MAXN << 2];
     53 
     54 void build(int p , int l , int r) {
     55     int mid = (l + r) >> 1;
     56     T[p].l = l , T[p].r = r , T[p].lazy = 0;
     57     if(l == r) {
     58         return ;
     59     }
     60     build(p << 1 , l , mid);
     61     build((p << 1)|1 , mid + 1 , r);
     62 }
     63 
     64 void pushup(int p) {
     65     if(T[p].lazy) {
     66         int ls = p << 1 , rs = (p << 1)|1;
     67         T[ls].lazy ^= 1;
     68         T[rs].lazy ^= 1;
     69         
     70         int temp;
     71         temp = T[ls].Max;
     72         T[ls].Max = -T[ls].Min;
     73         T[ls].Min = -temp;
     74 
     75         temp = T[rs].Max;
     76         T[rs].Max = -T[rs].Min;
     77         T[rs].Min = -temp;
     78         T[p].lazy = 0;
     79     }    
     80 }
     81 //更新操作就是 将原来的Max变成-Min ,Min变成-Max
     82 void updata(int p , int l , int r , int flag) {
     83     int mid = (T[p].r + T[p].l) >> 1;
     84     if(T[p].l == l && T[p].r == r) {
     85         T[p].lazy ^= flag;
     86         int temp = T[p].Max;
     87         T[p].Max = -T[p].Min;
     88         T[p].Min = -temp;
     89         return ;
     90     }
     91     pushup(p);
     92     if(r <= mid) {
     93         updata(p << 1 , l , r , flag);
     94     }
     95     else if(l > mid) {
     96         updata((p << 1)|1 , l , r , flag);
     97     }
     98     else {
     99         updata(p << 1 , l , mid , flag);
    100         updata((p << 1)|1 , mid + 1 , r , flag);
    101     }
    102     T[p].Max = max(T[p << 1].Max , T[(p << 1)|1].Max);
    103     T[p].Min = min(T[p << 1].Min , T[(p << 1)|1].Min);
    104 }
    105 
    106 int query(int p , int l , int r) {
    107     int mid = (T[p].l + T[p].r) >> 1;
    108     if(T[p].l == l && T[p].r == r) {
    109         return T[p].Max;
    110     }
    111     pushup(p);
    112     if(r <= mid) {
    113         return query(p << 1 , l , r);
    114     }
    115     else if(l > mid) {
    116         return query((p << 1)|1 , l , r);
    117     }
    118     else {
    119         return max(query(p << 1 , l , mid) , query((p << 1)|1 , mid + 1 , r));
    120     }
    121 }
    122 
    123 void updata_pos(int p , int pos , int num) {
    124     int mid = (T[p].l + T[p].r) >> 1;
    125     if(T[p].l == T[p].r && T[p].l == pos) {
    126         T[p].Max = T[p].Min = num;
    127         T[p].lazy = 0;
    128         return ;
    129     }
    130     pushup(p);
    131     if(pos <= mid) {
    132         updata_pos(p << 1 , pos , num);
    133     }
    134     else {
    135         updata_pos((p << 1)|1 , pos , num);
    136     }
    137     T[p].Max = max(T[p << 1].Max , T[(p << 1)|1].Max);
    138     T[p].Min = min(T[p << 1].Min , T[(p << 1)|1].Min);
    139 }
    140 
    141 int find_max(int u , int v) {
    142     int fu = top[u] , fv = top[v] , Max = -99999999;
    143     while(fv != fu) {
    144         if(dep[fu] > dep[fv]) {
    145             Max = max(Max , query(1 , id[fu] , id[u]));
    146             u = par[fu];
    147             fu = top[u];
    148         }
    149         else {
    150             Max = max(Max , query(1 , id[fv] , id[v]));
    151             v = par[fv];
    152             fv = top[v];
    153         }
    154     }
    155     if(v == u)
    156         return Max;
    157     else if(dep[u] > dep[v])
    158         return max(Max , query(1 , id[son[v]] , id[u]));
    159     else
    160         return max(Max , query(1 , id[son[u]] , id[v]));
    161 }
    162 
    163 void change(int u , int v) {
    164     int fu = top[u] , fv = top[v];
    165     while(fu != fv) {
    166         if(dep[fu] > dep[fv]) {
    167             updata(1 , id[fu] , id[u] , 1);
    168             u = par[fu];
    169             fu = top[u];
    170         }
    171         else {
    172             updata(1 , id[fv] , id[v] , 1);
    173             v = par[fv];
    174             fv = top[v];
    175         }
    176     }
    177     if(v == u)
    178         return ;
    179     else if(dep[u] > dep[v])
    180         updata(1 , id[son[v]] , id[u] , 1);
    181     else
    182         updata(1 , id[son[u]] , id[v] , 1);
    183 }
    184 
    185 int main() 
    186 {
    187     int t, n;
    188     scanf("%d", &t);
    189     while(t--) {
    190         init();
    191         scanf("%d" , &n);
    192         for(int i = 1 ; i < n ; ++i) {
    193             scanf("%d %d %d" , from + i , to + i , cost + i);
    194             add(from[i] , to[i] , cost[i]);
    195             add(to[i] , from[i] , cost[i]);
    196         }
    197         dfs1(1 , 1 , 0);
    198         dfs2(1 , 1 , 1);
    199         build(1 , 2 , cnt);
    200         for(int i = 1 ; i < n ; ++i) {
    201             if(dep[from[i]] < dep[to[i]])
    202                 swap(from[i] , to[i]);
    203             updata_pos(1 , id[from[i]] , cost[i]);
    204         }
    205         char q[10];
    206         int l , r;
    207         while(scanf("%s" , q) && q[0] != 'D') {
    208             scanf("%d %d" , &l , &r);
    209             if(q[0] == 'Q') {
    210                 printf("%d
    " , find_max(l , r));
    211             }
    212             else if(q[0] == 'N') {
    213                 change(l , r);
    214             }
    215             else {
    216                 updata_pos(1 , id[from[l]] , r);
    217             }
    218         }
    219     }
    220     return 0;
    221 }
  • 相关阅读:
    面向对象——多态
    面向对象——继承
    面向对象—封装
    数组
    控制语句
    认识Java
    出入境大厅流程
    2021上半年感想
    记录2020
    读后感《从三分钟热度到一万个小时》
  • 原文地址:https://www.cnblogs.com/Recoder/p/5521216.html
Copyright © 2020-2023  润新知