• [BZOJ3914]Jabby's shadows


    • 一棵 (n) 个点的无根树,每个点有颜色 (1)(2),初始颜色均为 (1),每条边有边权。
    • 两个点在同一个联通块,当且仅当,两点间路径上的所有点的颜色相同。
    • (m) 次操作,询问一个点所在联通块直径或修改一条链上点为同一种颜色。
    • (n, m leq 10^5)

    TopTree

    #include <bits/stdc++.h>
    #define dbg(...)                                           
      std::cerr << "33[32;1m", fprintf(stderr, __VA_ARGS__), 
          std::cerr << "33[0m"
    template <class T, class U>
    inline bool smin(T &x, const U &y) {
      return y < x ? x = y, 1 : 0;
    }
    template <class T, class U>
    inline bool smax(T &x, const U &y) {
      return x < y ? x = y, 1 : 0;
    }
    using LL = long long;
    using PII = std::pair<int, int>;
    inline char gc() {
      static constexpr int BufferSize = 1 << 22 | 5;
      static char buf[BufferSize], *p, *q;
      static std::streambuf *i = std::cin.rdbuf();
      return p == q ? p = buf, q = p + i->sgetn(p, BufferSize), p == q ? EOF : *p++ : *p++;
    }
    inline void pc(char c) {
      static std::streambuf *o = std::cout.rdbuf();
      o->sputc(c);
    }
    template <class T>
    inline void readInt(T &w) {
      char c, p = 0;
      while (!isdigit(c = gc())) p = c == '-';
      for (w = c & 15; isdigit(c = gc());) w = w * 10 + (c & 15);
      if (p) w = -w;
    }
    template <class T, class... U>
    inline void readInt(T &w, U &... a) {
      readInt(w), readInt(a...);
    }
    template <class T>
    inline void printInt(T w) {
      static char c[50], *p;
      if (w < 0) pc('-'), w = -w;
      if (w == 0) return pc('0');
      for (p = c; w; w /= 10) *++p = w % 10;
      while (p != c) pc(*p-- | '0');
      pc('
    ');
    }
    
    constexpr int N(1e5 + 5);
    struct VertexInfo {
      int c;
      VertexInfo() : c(0) {}
      void update(int x) { c = x; }
    };
    struct RakeInfo {
      std::array<int, 2> ld, lans;
      RakeInfo() { ld[0] = ld[1] = lans[0] = lans[1] = 0; }
      RakeInfo rake(RakeInfo a) {
        RakeInfo r;
        for (int i = 0; i < 2; i++) {
          r.ld[i] = std::max(ld[i], a.ld[i]);
          r.lans[i] = std::max({lans[i], a.lans[i], ld[i] + a.ld[i]});
        }
        return r;
      }
    } rNull;
    struct ClusterInfo : RakeInfo {
      std::array<int, 2> rd, rans, pld, prd, pans;
      std::array<bool, 2> pc;
      int len;
      ClusterInfo() : len(0) {
        rd[0] = rd[1] = rans[0] = rans[1] = pld[0] = pld[1] = prd[0] = prd[1] =
            pans[0] = pans[1] = 0;
        pc[0] = pc[1] = true;
      }
      ClusterInfo &base(int x) {
        len = x;
        return *this;
      }
      void reverse() {
        std::swap(ld, rd);
        std::swap(lans, rans);
        std::swap(pld, prd);
      }
      void update(int x) {
        if (pc[0] && pc[1]) return;
        pc[x] = true, pc[!x] = false;
        ld[x] = pld[x];
        rd[x] = prd[x];
        lans[x] = rans[x] = pans[x];
        ld[!x] = rd[!x] = lans[!x] = rans[!x] = 0;
      }
      ClusterInfo &compress(ClusterInfo a, ClusterInfo b, RakeInfo m,
                            VertexInfo x) {
        int c = x.c;
        pc[c] = a.pc[c] && b.pc[c];
        pc[!c] = false;
        len = a.len + b.len;
        ld = a.ld, lans = a.lans;
        rd = b.rd, rans = b.rans;
        if (a.pc[c]) {
          int l = std::max(m.ld[c], b.ld[c]);
          smax(ld[c], a.len + l);
          smax(lans[c], ld[c]);
          smax(lans[c], a.rd[c] + l);
          smax(lans[c], m.ld[c] + b.ld[c]);
          smax(lans[c], m.lans[c]);
          smax(lans[c], b.lans[c]);
        }
        if (b.pc[c]) {
          int r = std::max(m.ld[c], a.rd[c]);
          smax(rd[c], b.len + r);
          smax(rans[c], rd[c]);
          smax(rans[c], b.ld[c] + r);
          smax(rans[c], m.ld[c] + a.rd[c]);
          smax(rans[c], m.lans[c]);
          smax(rans[c], a.rans[c]);
        }
        for (int i = 0; i < 2; i++) {
          pld[i] = std::max({a.pld[i], a.len + b.pld[i], a.len + m.ld[i]});
          prd[i] = std::max({b.prd[i], b.len + a.prd[i], b.len + m.ld[i]});
          pans[i] = std::max({a.pans[i], b.pans[i], m.lans[i], a.prd[i] + b.pld[i],
                              a.prd[i] + m.ld[i], m.ld[i] + b.pld[i]});
        }
        return *this;
      }
    } cNull;
    struct SplayTree {
      SplayTree *ch[3], *fa;
      SplayTree() { ch[0] = ch[1] = ch[2] = fa = nullptr; }
      bool nrt() const { return fa && (fa->ch[0] == this || fa->ch[1] == this); }
      bool dir() const { return fa->ch[1] == this; }
      void sch(int d, SplayTree *c) {
        ch[d] = c;
        if (c) c->fa = this;
      }
      void rotate() {
        SplayTree *p = fa;
        bool d = dir();
        fa = p->fa;
        if (fa) {
          fa->ch[fa->ch[2] == p ? 2 : p->dir()] = this;
        }
        p->sch(d, ch[!d]), sch(!d, p);
        p->pushup();
      }
      void update() {
        if (nrt()) fa->update();
        pushdown();
      }
      void splay() {
        for (update(); nrt(); rotate()) {
          if (fa->nrt()) {
            (fa->dir() == dir() ? fa : this)->rotate();
          }
        }
        pushup();
      }
      virtual void pushup() {}
      virtual void pushdown() {}
      virtual ~SplayTree() {}
    };
    #define cch(i) static_cast<CompressTree *>(ch[i])
    #define rch(i) static_cast<RakeTree *>(ch[i])
    struct RakeTree : SplayTree {
      RakeInfo rInfo;
      void pushup();
    };
    struct CompressTree : SplayTree {
      bool rev;
      int tag;
      ClusterInfo cInfo;
      VertexInfo vInfo;
      CompressTree() : rev(false), tag(-1), cInfo(), vInfo() {}
      void pushup();
      void reverse() {
        rev = !rev;
        std::swap(ch[0], ch[1]);
        cInfo.reverse();
      }
      void update(int x) {
        tag = x;
        vInfo.update(x);
        cInfo.update(x);
      }
      void pushdown() {
        if (rev) {
          if (ch[0]) cch(0)->reverse();
          if (ch[1]) cch(1)->reverse();
          rev = false;
        }
        if (tag != -1) {
          if (ch[0]) cch(0)->update(tag);
          if (ch[1]) cch(1)->update(tag);
          tag = -1;
        }
      }
      void access() {
        splay();
        if (ch[1]) {
          auto r = new RakeTree;
          r->sch(0, ch[2]), r->sch(2, ch[1]), r->pushup();
          ch[1] = nullptr, sch(2, r), pushup();
        }
        for (; fa; rotate()) {
          fa->splay();
          SplayTree *m = fa, *p = m->fa;
          assert(p);
          p->splay();
          m->pushdown();
          if (p->ch[1]) {
            m->sch(2, p->ch[1]);
            m->pushup();
          } else {
            if (!m->ch[0]) {
              p->sch(2, m->ch[1]);
            } else if (!m->ch[1]) {
              p->sch(2, m->ch[0]);
            } else {
              auto x = m->ch[0];
              x->fa = nullptr;
              while (x->pushdown(), x->ch[1]) x = x->ch[1];
              x->splay();
              p->sch(2, x);
              x->sch(1, m->ch[1]);
              x->pushup();
            }
            delete m;
          }
          p->sch(1, this);
        }
        pushup();
      }
      void evert() { access(), reverse(), pushdown(); }
    };
    inline void RakeTree::pushup() {
      auto &a = ch[0] ? rch(0)->rInfo : rNull;
      auto &b = ch[1] ? rch(1)->rInfo : rNull;
      auto &c = ch[2] ? cch(2)->cInfo : cNull;
      rInfo = a.rake(c.rake(b));
    }
    inline void CompressTree::pushup() {
      auto &a = ch[0] ? cch(0)->cInfo : cNull;
      auto &b = ch[1] ? cch(1)->cInfo : cNull;
      auto &c = ch[2] ? rch(2)->rInfo : rNull;
      cInfo.compress(a, b, c, vInfo);
    }
    CompressTree *link(CompressTree *x, CompressTree *y, int len) {
      x->access(), y->evert();
      auto e = new CompressTree;
      e->cInfo.base(len);
      x->sch(1, y), y->sch(0, e);
      y->pushup(), x->pushup();
      return x;
    }
    int main() {
      double sta = (double)clock() / CLOCKS_PER_SEC;
      int n, m;
      readInt(n);
      CompressTree *t = new CompressTree[n + 1];
      std::vector<int> p(n);
      for (int i = 1; i < n; i++) readInt(p[i]);
      for (int i = 1, x; i < n; i++) {
        readInt(x);
        auto r = t + i + 1;
        link(t + p[i], t + i + 1, x);
      }
      readInt(m);
      while (m--) {
        int opt, x, y, z;
        readInt(opt, x);
        if (opt == 1) {
          t[x].access();
          int d = t[x].cInfo.rans[t[x].vInfo.c];
          if (d) {
            printInt(d);
          } else {
            pc('Q'), pc('w'), pc('Q'), pc('
    ');
          }
        } else {
          readInt(y, z);
          t[x].evert(), t[y].access();
          t[y].update(z - 1);
        }
      }
      dbg("time : %.5f
    ", (double)clock() / CLOCKS_PER_SEC - sta);
      return 0;
    }
    
  • 相关阅读:
    Ubuntu下安装、激活并配置Pycharm
    高分辨率下firefox字体和界面自动放大的问题
    Java如何根据IP获取当前定位
    WebSocket介绍和一个简单的聊天室
    java注解处理
    TCP/IP协议三次握手与四次握手流程解析
    mybatis如何做分页处理
    xshell学习笔记
    正交表生成工具 PICT 成对组合覆盖 收藏
    Ready api groovy script 参数化
  • 原文地址:https://www.cnblogs.com/HolyK/p/14332568.html
Copyright © 2020-2023  润新知