首页 > 其他分享 >洛谷 P3401

洛谷 P3401

时间:2022-10-25 08:57:10浏览次数:64  
标签:P3401 lazy 洛谷 int top dep now rk

甚么神仙题啊……

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iterator>
#include <utility>

#define int long long

using namespace std;

const int N = 3e4 + 10;
int n;
int q;
int dep[N];
int sz[N];
int fa[N];
int len[N];
int rk[N];
int top[N];
int dfs_order[N];
int son[N];
int cnt;
int w[N];
int qwq[N];
int a[N];
vector <pair <int, int> > zz[N];

struct Node
{
  int l;
  int r;
  int lazy;
  int sum[15];
  int x0;
  int x1;
  int cnt0[15];
  int cnt1[15];
  Node ()
  {
    l = 0;
    r = 0;
    memset (sum, 0, sizeof sum);
    memset (cnt0, 0, sizeof cnt0);
    memset (cnt1, 0, sizeof cnt1);
    lazy = 0;
    x0 = 0;
    x1 = 0;
  }
  ~Node ()
  {
    l = 0;
    r = 0;
    memset (sum, 0, sizeof sum);
    memset (cnt0, 0, sizeof cnt0);
    memset (cnt1, 0, sizeof cnt1);
    lazy = 0;
    x0 = 0;
    x1 = 0;
  }
  void color(int p)
  {
    lazy ^= (1 << p);
    if (sum[p] == 1)
    {
      sum[p] = 0;
    }
    else
    {
      sum[p] = 1;
    }
    x0 = x0 - cnt0[p] + cnt1[p];
    x1 = x1 - cnt1[p] + cnt0[p];
    swap (cnt0[p], cnt1[p]);
  }
  void init(int p)
  {
    l = p;
    r = p;
    for (int i = 0; i < 10; i ++)
    {
      if (qwq[p] & (1 << i))
      {
        sum[i] = 1;
        cnt1[i] = 1;
      }
      else
      {
        cnt0[i] = 1;
      }
    }
    for (int i = 0; i < 10; i ++)
    {
      if (sum[i])
      {
        x1 ++;
      }
      else
      {
        x0 ++;
      }
    }
    lazy = 0;
  }
  int query()
  {
    int x = 0;
    for (int i = 9; ~i; i --)
    {
      x = x << 1 | sum[i];
    }
    return x;
  }
}
z[N << 2];

Node operator + (const Node &lhs, const Node &rhs)
{
  Node ans;
  ans.l = lhs.l;
  ans.r = rhs.r;
  for (int i = 0; i < 10; i ++)
  {
    ans.sum[i] = lhs.sum[i] + rhs.sum[i];
  }
  for (int i = 0; i < 10; i ++)
  {
    ans.cnt0[i] = lhs.cnt0[i] + rhs.cnt0[i];
  }
  for (int i = 0; i < 10; i ++)
  {
    ans.cnt1[i] = lhs.cnt1[i] + rhs.cnt1[i];
  }
  ans.lazy = 0;
  ans.x0 = lhs.x0 + rhs.x0;
  ans.x1 = lhs.x1 + rhs.x1;
  return ans;
}

void build(int l, int r, int rt)
{
  if (l == r)
  {
    z[rt].init(l);
    return ;
  }
  int mid = l + r >> 1;
  build(l, mid, rt << 1);
  build(mid + 1, r, rt << 1 | 1);
  z[rt] = z[rt << 1] + z[rt << 1 | 1];
}

void dfs1(int now, int fat = -1)
{
  dep[now] = dep[fa[now]] + 1;
  sz[now] = 1;
  for (auto &[u, v] : zz[now])
  {
    if (u != fat)
    {
      a[u] = v;
      w[u] = w[now] ^ v;
      fa[u] = now;
      dfs1(u, now);
      sz[now] += sz[u];
      if (sz[u] > sz[son[now]])
      {
        son[now] = u;
      }
    }
  }
}

void dfs2(int now, int h, int fat = -1)
{
  cnt ++;
  dfs_order[cnt] = now;
  rk[now] = cnt;
  qwq[cnt] = w[now];
  top[now] = h;
  len[h] ++;
  int p = -1;
  for (auto &[u, v] : zz[now])
  {
    if (u != fat)
    {
      if (p == -1)
      {
        p = u;
      }
      else
      {
        if (sz[u] > sz[p])
        {
          p = u;
        }
      }
    }
  }
  if (p == -1)
  {
    return ;
  }
  dfs2(p, h, now);
  for (auto &[u, v] : zz[now])
  {
    if (p != u)
    {
      if (u != fat)
      {
        dfs2(u, u, now);
      }
    }
  }
}

int lca(int x, int y)
{
  while (top[x] != top[y])
  {
    if (dep[top[x]] < dep[top[y]])
    {
      swap(x, y);
    }
    x = fa[top[x]];
  }
  if (dep[x] < dep[y])
  {
    return x;
  }
  else
  {
    return y;
  }
}

void push_lazy(int rt)
{
  int la = z[rt].lazy;
  for (int i = 0; i < 10; i ++)
  {
    if (la & (1 << i))
    {
      z[rt << 1].color(i);
      z[rt << 1 | 1].color(i);
    }
  }
  z[rt].lazy = 0;
}

void modify(int l, int r, int rt, int nowl, int nowr, int value)
{
  if (nowl <= l)
  {
    if (r <= nowr)
    {
      z[rt].color(value);
      return ;
    }
  }
  int mid = l + r >> 1;
  push_lazy(rt);
  if (nowl <= mid)
  {
    modify(l, mid, rt << 1, nowl, nowr, value);
  }
  if (mid < nowr)
  {
    modify(mid + 1, r, rt << 1 | 1, nowl, nowr, value);
  }
  z[rt] = z[rt << 1] + z[rt << 1 | 1];
}

void modify_tree(int p, int c)
{
  for (int i = 0; i < 10; i ++)
  {
    if ((a[p] ^ c) >> i & 1)
    {
      modify(1, n, 1, rk[p], rk[p] + sz[p] - 1, i);
    }
  }
  a[p] = c;
}

int query(int l, int r, int rt, int nowl, int nowr)
{
  if (nowl <= l)
  {
    if (r <= nowr)
    {
      return z[rt].query();
    }
  }
  push_lazy(rt);
  int ans = 0;
  int mid = l + r >> 1;
  if (nowl <= mid)
  {
    ans ^= query(l, mid, rt << 1, nowl, nowr);
  }
  if (mid < nowr)
  {
    ans ^= query(mid + 1, r, rt << 1 | 1, nowl, nowr);
  }
  return ans;
}

int query_link(int p1, int p2)
{
  int ans = 0;
  while (true)
  {
    if (top[p1] == top[p2])
    {
      if (dep[p1] > dep[p2])
      {
        swap(p1, p2);
      }
      ans ^= query(1, n, 1, rk[p1], rk[p2]);
      break;
    }
    else
    {
      if (dep[top[p1]] < dep[top[p2]])
      {
        swap (p1, p2);
      }
      int p3 = top[p1];
      ans ^= query(1, n, 1, rk[p3], rk[p1]);
      p1 = fa[p3];
    }
  }
  return ans;
}

Node que(int l, int r, int rt, int nowl, int nowr)
{
  if (nowl <= l)
  {
    if (r <= nowr)
    {
      return z[rt];
    }
  }
  int mid = l + r >> 1;
  push_lazy(rt);
  if (nowr <= mid)
  {
    return que(l, mid, rt << 1, nowl, nowr);
  }
  if (mid < nowl)
  {
    return que(mid + 1, r, rt << 1 | 1, nowl, nowr);
  }
  return que(l, mid, rt << 1, nowl, nowr) + que(mid + 1, r, rt << 1 | 1, nowl, nowr);
}

int query(int x, int y)
{
  int c1[20] = {0};
  int c0[20] = {0};
  while (top[x] != top[y])
  {
    if (dep[top[x]] < dep[top[y]])
    {
      swap (x, y);
    }
    Node orz = que(1, n, 1, rk[top[x]], rk[x]);
    for (int i = 0; i < 10; i ++)
    {
      c1[i] += orz.cnt1[i];
      c0[i] += orz.cnt0[i];
    }
    x = fa[top[x]];
  }
  if (rk[x] > rk[y])
  {
    swap (x, y);
  }
  Node orz = que(1, n, 1, rk[x], rk[y]);
  for (int i = 0; i < 10; i ++)
  {
    c1[i] += orz.cnt1[i];
    c0[i] += orz.cnt0[i];
  }
  int ans = 0;
  for (int i = 0; i < 10; i ++)
  {
    ans = ans + (1 << i) * c1[i] * c0[i];
  }
  return ans;
}

signed main()
{
  cin >> n >> q;
  for (int i = 1; i < n; i ++)
  {
    int u, v, w;
    cin >> u >> v >> w;
    zz[u].push_back(make_pair(v, w));
    zz[v].push_back(make_pair(u, w));
  }
  dfs1(1);
  dfs2(1, 1);
  build(1, n, 1);
  while (q --)
  {
    int opt;
    cin >> opt;
    if (opt == 1)
    {
      int u, v;
      cin >> u >> v;
      cout << query(u, v) << '\n';
    }
    else
    {
      int u, v, w;
      cin >> u >> v >> w;
      int c = query_link(u, v);
      if (dep[u] < dep[v])
      {
        modify_tree(v, w);
      }
      else
      {
        modify_tree(u, w);
      }
    }
  }
  return 0;
}

标签:P3401,lazy,洛谷,int,top,dep,now,rk
From: https://www.cnblogs.com/BaiduFirstSearch/p/16823737.html

相关文章

  • 洛谷上扒的DP练习题
    DP综述最优子结构:把原问题化到规模更小的问题后,原问题的最优解一定能从规模更小问题的最优解推出。无后效性:如果在某个阶段上过程的状态已知,则从此阶段以后过程的发展变......
  • 洛谷 P8089
    考虑对于满二叉树,显然只与\(dep\)有关,设\(f_{i}\)表示深度为\(i\)的答案(确切的说应该是到最深深度的距离),则有\(f_1=1,f_i=(f_{i-1}+1)^2(i\ge2)\)。则对于完全二叉......
  • 洛谷P5020题解
    原题P5020[NOIP2018提高组]货币系统思路概述题意分析给定包含一个整数\(n\)和一个正整数集合\(a\)的货币系统\((n,a)\),要求将其化简,输出最简的货币系统中的面......
  • 洛谷P2827题解
    原题P2827[NOIP2016提高组]蚯蚓思路概述题意分析给定整数\(n,m,q,u,v,t\)和一个数列\(\{a\}\),进行\(m\)次操作如下:每次选取其中最大数\(x\)切分为\([px],x......
  • 「题解」洛谷 P8529 [Ynoi2003] 赫露艾斯塔
    构造半平面莫队?/jk注意到对于一个半平面的直线,通过平移和旋转经过的点数,一定大于等于它们的对称差,因为对称差中的点会被经过奇数次,不在对称差中的点会被经过偶数次。那么......
  • 洛谷 P3224 [HNOI2012]永无乡 题解
    查询第\(k\)小值想到权值线段树。合并操作想到线段树合并。维护连通性想到并查集。并查集合并方向应与线段树合并方向一致。查询时,先求出并查集的根再在线段树上询......
  • 洛谷P8060 [POI2003] Sums
    题目链接题意给定序列\(a_1,a_2,\cdots,a_n\),将其划分为若干段,要求子段和单调不增,求最大段数。数据范围:\(1\len\le10^5,1\lea_i\le10^4\)。题解考虑逆推。问题......
  • 洛谷P1928 外星密码
    一波小解释本人第一次写博客,单纯是为了记录,可能只有自己能看懂哈哈,第一次语法格式什么的还把握不好希望谅解。外星密码题目描述有了防护伞,并不能完全避免2012的灾难......
  • 洛谷 P8268 [USACO22OPEN] Alchemy B 题解
    Part0题意简述原题给出拥有的金属数量与金属配方,求金属\(N\)最大能合成的数量。Part1题目分析首先,金属\(i\)能配出的最大数量只和它的原数量和它的配方中能合......
  • 洛谷 题解 P1572 计算分数
    题目描述Csh被老妈关在家里做分数计算题,但显然他不愿意坐这么多复杂的计算。况且在家门口还有Xxq在等着他去一起看电影。为了尽快地能去陪Xxq看电影,他把剩下的计算题......