Alex_tz307

USACO 2019 February Contest, Gold Problem 1. Cow Land

Mar 18th, 2021 (edited)
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.45 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. ifstream fin("cowland.in");
  6. ofstream fout("cowland.out");
  7.  
  8. const int NMAX = 1e5 + 5;
  9. int a[NMAX];
  10.  
  11. struct SegTree {
  12.   int Size;
  13.   vector<int> tree;
  14.  
  15.   void init(int N) {
  16.     Size = 1;
  17.     while (Size < N)
  18.       Size <<= 1;
  19.     tree.resize(Size << 1 | 1);
  20.   }
  21.  
  22.   void build(int x, int lx, int rx) {
  23.     if (lx == rx) {
  24.       tree[x] = a[lx];
  25.       return;
  26.     }
  27.     int mid = (lx + rx) >> 1;
  28.     build(x << 1, lx, mid);
  29.     build(x << 1 | 1, mid + 1, rx);
  30.     tree[x] = tree[x << 1] ^ tree[x << 1 | 1];
  31.   }
  32.  
  33.   void update(int x, int lx, int rx, int poz, int val) {
  34.     if (lx == rx) {
  35.       tree[x] = val;
  36.       return;
  37.     }
  38.     int mid = (lx + rx) >> 1;
  39.     if (poz <= mid)
  40.       update(x << 1, lx, mid, poz, val);
  41.     else
  42.       update(x << 1 | 1, mid + 1, rx, poz, val);
  43.     tree[x] = tree[x << 1] ^ tree[x << 1 | 1];
  44.   }
  45.  
  46.   int query(int x, int lx, int rx, int st, int dr) {
  47.     if (st <= lx && rx <= dr)
  48.       return tree[x];
  49.     int mid = (lx + rx) >> 1, ans1 = 0, ans2 = 0;
  50.     if (st <= mid)
  51.       ans1 = query(x << 1, lx, mid, st, dr);
  52.     if (mid < dr)
  53.       ans2 = query(x << 1 | 1, mid + 1, rx, st, dr);
  54.     return ans1 ^ ans2;
  55.   }
  56. } tree;
  57.  
  58. int N, Q, v[NMAX]; /// numarul de noduri, de query-uri, valorile initiale
  59. vector<int> G[NMAX]; /// arborele
  60. int p[NMAX]; /// tatal nodului
  61. int sz[NMAX]; /// dimensiunea subarborelui cu radacina in nod
  62. int depth[NMAX]; /// adancimea / nivelul in arbore
  63. int chain_top[NMAX]; /// capul chain-ului(cel mai apropiat de radacina nod din chain)
  64. int cnt_labels, label[NMAX]; /// le voi da nodurilor valori astfel incat sa am chain-urile numerotate consecutiv sa pot face aint pe ele
  65.  
  66. void read_input() {
  67.   fin >> N >> Q;
  68.   for (int i = 1; i <= N; ++i)
  69.     fin >> v[i];
  70.   for (int i = 1; i < N; ++i) {
  71.     int x, y;
  72.     fin >> x >> y;
  73.     G[x].emplace_back(y);
  74.     G[y].emplace_back(x);
  75.   }
  76. }
  77.  
  78. void dfs_init(int u, int parent) {
  79.   p[u] = parent;
  80.   depth[u] = depth[parent] + 1;
  81.   sz[u] = 1;
  82.   chain_top[u] = u;
  83.   for (int v : G[u])
  84.     if (v != parent) {
  85.       dfs_init(v, u);
  86.       sz[u] += sz[v];
  87.     }
  88. }
  89.  
  90. void dfs_heavy(int u) {
  91.   label[u] = ++cnt_labels;
  92.   int max_size = -1, heavy_son = -1;
  93.   for (int v : G[u])
  94.     if (v != p[u] && sz[v] > max_size) {
  95.       max_size = sz[v];
  96.       heavy_son = v;
  97.     }
  98.   if(heavy_son == -1)
  99.     return;
  100.   chain_top[heavy_son] = chain_top[u];
  101.   dfs_heavy(heavy_son);
  102.   for (int v : G[u])
  103.     if (v != p[u] && v != heavy_son)
  104.       dfs_heavy(v);
  105. }
  106.  
  107. int lca_query(int x, int y) {
  108.   if (chain_top[x] == chain_top[y]) { /// x si y fac parte din acelasi chain
  109.     if (label[x] > label[y])
  110.       swap(x, y);
  111.     return tree.query(1, 1, N, label[x], label[y]);
  112.   }
  113.   if (depth[p[chain_top[x]]] > depth[p[chain_top[y]]])
  114.     return tree.query(1, 1, N, label[chain_top[x]], label[x]) ^ lca_query(p[chain_top[x]], y);
  115.   return tree.query(1, 1, N, label[chain_top[y]], label[y]) ^ lca_query(x, p[chain_top[y]]);
  116. }
  117.  
  118. void solve() {
  119.   dfs_init(1, 0);
  120.   dfs_heavy(1);
  121.   tree.init(N);
  122.   for (int i = 1; i <= N; ++i)
  123.     a[label[i]] = v[i];
  124.   tree.build(1, 1, N);
  125.   for (int q = 0; q < Q; ++q) {
  126.     int op, x, y;
  127.     fin >> op >> x >> y;
  128.     if (op == 1)
  129.       tree.update(1, 1, N, label[x], y);
  130.     else
  131.       fout << lca_query(x, y) << '\n';
  132.   }
  133. }
  134.  
  135. void close_files() {
  136.   fin.close();
  137.   fout.close();
  138. }
  139.  
  140. int main() {
  141.   read_input();
  142.   solve();
  143.   close_files();
  144.   return 0;
  145. }
  146.  
Add Comment
Please, Sign In to add comment