結果

問題 No.2296 Union Path Query (Hard)
ユーザー 👑 tute7627tute7627
提出日時 2023-05-05 22:37:35
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 11,253 bytes
コンパイル時間 2,695 ms
コンパイル使用メモリ 221,920 KB
実行使用メモリ 147,712 KB
最終ジャッジ日時 2024-05-02 17:33:14
合計ジャッジ時間 53,031 ms
ジャッジサーバーID
(参考情報)
judge5 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 72 ms
81,536 KB
testcase_02 AC 72 ms
81,536 KB
testcase_03 AC 70 ms
81,536 KB
testcase_04 WA -
testcase_05 WA -
testcase_06 WA -
testcase_07 WA -
testcase_08 WA -
testcase_09 WA -
testcase_10 WA -
testcase_11 WA -
testcase_12 WA -
testcase_13 WA -
testcase_14 WA -
testcase_15 WA -
testcase_16 WA -
testcase_17 WA -
testcase_18 AC 1,604 ms
142,464 KB
testcase_19 AC 1,460 ms
77,312 KB
testcase_20 AC 1,561 ms
142,592 KB
testcase_21 AC 1,706 ms
131,584 KB
testcase_22 AC 1,711 ms
130,048 KB
testcase_23 AC 728 ms
143,880 KB
testcase_24 AC 856 ms
73,716 KB
testcase_25 AC 507 ms
124,416 KB
testcase_26 AC 507 ms
124,544 KB
testcase_27 AC 626 ms
124,416 KB
testcase_28 AC 639 ms
124,416 KB
testcase_29 AC 501 ms
130,688 KB
testcase_30 AC 513 ms
130,560 KB
testcase_31 AC 637 ms
140,032 KB
testcase_32 AC 729 ms
136,192 KB
testcase_33 AC 847 ms
128,256 KB
testcase_34 AC 689 ms
120,576 KB
testcase_35 AC 738 ms
116,608 KB
testcase_36 AC 1,138 ms
102,656 KB
testcase_37 AC 758 ms
105,600 KB
testcase_38 AC 753 ms
105,728 KB
testcase_39 AC 795 ms
105,600 KB
testcase_40 AC 786 ms
105,600 KB
testcase_41 AC 2 ms
5,376 KB
testcase_42 AC 1 ms
5,376 KB
testcase_43 AC 2 ms
5,376 KB
testcase_44 AC 718 ms
143,888 KB
testcase_45 AC 741 ms
143,872 KB
testcase_46 AC 810 ms
145,920 KB
testcase_47 AC 833 ms
147,712 KB
testcase_48 AC 788 ms
145,024 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using int64=ll;
long long infll=1e15;
long long inf=1e18;
long long infll2=2e15;

template< typename SUM, typename KEY >
struct LinkCutTreeSubtree {

  struct Node {
    Node *l, *r, *p;

    KEY key;
    SUM sum;

    bool rev;
    int sz;

    bool is_root() const {
      return !p || (p->l != this && p->r != this);
    }

    Node(const KEY &key, const SUM &sum) :
        key(key), sum(sum), rev(false), sz(1),
        l(nullptr), r(nullptr), p(nullptr) {}
  };

  const SUM ident;

  LinkCutTreeSubtree(const SUM &ident) : ident(ident) {}

  Node *make_node(const KEY &key) {
    auto ret = new Node(key, ident);
    update(ret);
    return ret;
  }

  Node *set_key(Node *t, const KEY &key) {
    expose(t);
    t->key = key;
    update(t);
    return t;
  }

  void toggle(Node *t) {
    swap(t->l, t->r);
    t->sum.toggle();
    t->rev ^= true;
  }

  void push(Node *t) {
    if(t->rev) {
      if(t->l) toggle(t->l);
      if(t->r) toggle(t->r);
      t->rev = false;
    }
  }


  void update(Node *t) {
    t->sz = 1;
    if(t->l) t->sz += t->l->sz;
    if(t->r) t->sz += t->r->sz;
    t->sum.merge(t->key, t->l ? t->l->sum : ident, t->r ? t->r->sum : ident);
  }

  void rotr(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->l = t->r)) t->r->p = x;
    t->r = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }

  void rotl(Node *t) {
    auto *x = t->p, *y = x->p;
    if((x->r = t->l)) t->l->p = x;
    t->l = x, x->p = t;
    update(x), update(t);
    if((t->p = y)) {
      if(y->l == x) y->l = t;
      if(y->r == x) y->r = t;
      update(y);
    }
  }


  void splay(Node *t) {
    push(t);
    while(!t->is_root()) {
      auto *q = t->p;
      if(q->is_root()) {
        push(q), push(t);
        if(q->l == t) rotr(t);
        else rotl(t);
      } else {
        auto *r = q->p;
        push(r), push(q), push(t);
        if(r->l == q) {
          if(q->l == t) rotr(q), rotr(t);
          else rotl(t), rotr(t);
        } else {
          if(q->r == t) rotl(q), rotl(t);
          else rotr(t), rotl(t);
        }
      }
    }
  }


  Node *expose(Node *t) {
    Node *rp = nullptr;
    for(auto *cur = t; cur; cur = cur->p) {
      splay(cur);
      if(cur->r) cur->sum.add(cur->r->sum);
      cur->r = rp;
      if(cur->r) cur->sum.erase(cur->r->sum);
      update(cur);
      rp = cur;
    }
    splay(t);
    return rp;
  }

  void link(Node *child, Node *parent) {
    expose(child);
    expose(parent);
    child->p = parent;
    parent->r = child;
  }

  void cut(Node *child) {
    expose(child);
    auto *parent = child->l;
    child->l = nullptr;
    parent->p = nullptr;
    update(child);
  }

  void evert(Node *t) {
    expose(t);
    toggle(t);
    push(t);
  }

  Node *lca(Node *u, Node *v) {
    if(get_root(u) != get_root(v)) return nullptr;
    expose(u);
    return expose(v);
  }


  Node *get_kth(Node *x, int k) {
    expose(x);
    while(x) {
      push(x);
      if(x->r && x->r->sz > k) {
        x = x->r;
      } else {
        if(x->r) k -= x->r->sz;
        if(k == 0) return x;
        k -= 1;
        x = x->l;
      }
    }
    return nullptr;
  }

  Node *get_root(Node *x) {
    expose(x);
    while(x->l) {
      push(x);
      x = x->l;
    }
    return x;
  }
};

struct PQ {
  priority_queue< int64 > in, out;
 
  inline int64 top() {
    if(!in.empty()) return in.top();
    return -infll;
  }
 
  inline void insert(int64 k) {
    if(k < -inf) return;
    in.emplace(k);
  }
 
  inline void erase(int64 k) {
    if(k < -inf) return;
    out.emplace(k);
    while(out.size() && in.top() == out.top()) {
      in.pop();
      out.pop();
    }
  }
 
  inline int64 top2() {
    if(in.empty()) return -infll;
    int64 top = in.top();
    erase(top);
    int64 top2 = this->top();
    in.push(top);
    return top2;
  }
};
template<typename T,typename OT>
struct LinkCutTree{
  using F = function<T(T, T)>;
  using G = function<T(T, OT)>;
  using H = function<OT(OT, OT)>;
  using S = function<T(T)>;
  struct Node{
    Node *p,*l,*r;
    int idx;
    T key, sum;
    OT lazy;
    int sz;
    bool rev;
    bool is_root(){
      return !p || (p->l != this && p->r != this);
    }
    Node(int idx, const T &key,const OT &om):
      idx(idx),key(key),sum(key),lazy(om),sz(1),
      l(nullptr),r(nullptr),p(nullptr),rev(false){}
  };
  const T M1;
  const OT OM0;
  const F f;
  const G g;
  const H h;
  const S s;
  vector<Node *>ver;
  LinkCutTree(int n):
    LinkCutTree(n,[&](T x,T y){return x;},[&](T x){return x;},T()){}
  LinkCutTree(int n,const F &f,const S &s,const T M1):
    LinkCutTree(n,f,G(),H(),s,M1,OT()){}
  LinkCutTree(int n,const F &f,const G &g,const H &h, const S &s,const T M1,const OT OM0)
    :f(f),g(g),h(h),s(s),ver(n),M1(M1),OM0(OM0){}
  void update(Node *t){
    t->sz = 1;
    t->sum = t->key;
    if(t->l)t->sz += t->l->sz, t->sum = f(t->l->sum, t->sum);
    if(t->r)t->sz += t->r->sz, t->sum = f(t->sum, t->r->sum);
  }
  void rotr(Node *t){
    Node *x = t->p, *y = x->p;
    if((x->l = t->r))t->r->p = x;
    t->r = x, x->p = t;
    update(x),update(t);
    if((t->p = y)){
      if(y->l == x)y->l = t;
      if(y->r == x)y->r = t;
      update(y);
    }
  }
  void rotl(Node *t){
    Node *x =t->p, *y = x->p;
    if((x->r = t->l))t->l->p = x;
    t->l = x, x->p = t;
    update(x),update(t);
    if((t->p = y)){
      if(y->l == x)y->l = t;
      if(y->r == x)y->r = t;
      update(y);
    }
  }
  void splay(Node *t){
    push(t);
    while(!t->is_root()){
      Node *q = t->p;
      if(q->is_root()){
        push(q), push(t);
        if(q->l == t)rotr(t);
        else rotl(t);
      }
      else{
        Node *r = q->p;
        push(r), push(q), push(t);
        if(r->l == q){
          if(q->l == t)rotr(q), rotr(t);
          else rotl(t), rotr(t);
        }
        else{
          if(q->r == t)rotl(q), rotl(t);
          else rotr(t), rotl(t);
        }
      }
    }
  }
  Node *expose(Node *t){
    Node *rp = nullptr;
    Node *cur = t;
    while(cur){
      splay(cur);
      cur->r = rp;
      update(cur);
      rp = cur;
      cur = cur->p;
    }
    splay(t);
    return rp;
  }
  void link(Node *child, Node *parent){
    expose(child);
    expose(parent);
    child->p = parent;
    parent->r = child;
    update(parent);
  }
  void cut(Node *child){
    expose(child);
    Node *parent = child->l;
    child->l = nullptr;
    parent->p = nullptr;
    update(child);
  }
  void toggle(Node *t){
    assert(t);
    swap(t->l,t->r);
    t->sum = s(t->sum);
    t->rev^=true;
  }
  void evert(Node *t){
    expose(t);
    toggle(t);
    push(t);
  }
  Node *make_node(int idx,T v = T()){
    return new Node(idx, v, OM0);
  }
  void push(Node *t){
    if(t->lazy != OM0){
      if(t->l)propagate(t->l, t->lazy);
      if(t->r)propagate(t->r, t->lazy);
      t->lazy = OM0;
    }
    if(t->rev){
      if(t->l)toggle(t->l);
      if(t->r)toggle(t->r);
      t->rev=false;
    }
  }
  Node *lca(Node *u, Node *v){
    expose(u);
    return expose(v);
  }
  void propagate(Node *t, const OT x){
    t->lazy = h(t->lazy, x);
    t->key = g(t->key, x);
    t->sum = g(t->sum, x);
  }
  //ここから操作
  void add_vertex(int idx,T v = T()){//頂点idxの追加
    ver[idx] = make_node(idx, v);
  }
  void evert(int x){//根をxに
    evert(ver[x]);
  }
  void add_edge(int x,int y){//(x->y)の追加
    evert(y);
    link(ver[y],ver[x]);
  }
  void cut_edge(int x,int y){
    evert(x);
    cut(ver[y]);
  }
  T val(int x){
    return ver[x]->key;
  }
  T val_path(int x){//根~xのパスクエリ
    expose(ver[x]);
    return ver[x]->sum;
  }
  T val_path(int x,int y){//x->yのパスクエリ
    evert(x);
    return val_path(y);
  }
  void update(int x,T v){//頂点xの値をvに
    expose(ver[x]);
    ver[x]->key = v;
    update(ver[x]);
  }
  void update_path(int x,const OT v){//根~xのパス更新
    expose(ver[x]);
    propagate(ver[x], v);
    push(ver[x]);
  }
  void update_path(int x,int y,const OT v){//x~yのパス更新
    evert(x);
    update_path(y,v);
  }
  int lca(int x,int y){
    return lca(ver[x], ver[y])->idx;
  }
  bool connected(int x,int y){//頂点xとyが連結か?
    if(x==y)return true;
    expose(ver[x]);
    expose(ver[y]);
    return bool(ver[x]->p);
  }
  int parent(int x,int r){//根がrの時のxの親 存在しない場合は-1
    evert(r);
    expose(ver[x]);
    Node *t = ver[x]->l;
    if(!t)return -1;
    push(t);
    while(t->r){
      t = t->r;
      push(t);
    }
    return t->idx;
  }
  int root(int x){
    expose(ver[x]);
    Node *t = ver[x];
    push(t);
    while(t->l){
      t = t->l;
      push(t);
    }
    return t->idx;
  }
};
int main() {
  int N;
  cin>>N;
 
 
  using Key = int64;
 
  struct Sum {
    int64 all;
    int64 p_len, c_len;
    int64 diameter;
 
    PQ md1, md2;
 
    Sum() : all(0), p_len(-infll), c_len(-infll), diameter(-infll) {}
 
 
    void toggle() {
      swap(p_len, c_len);
    }
 
    void merge(Key key, const Sum &parent, const Sum &child) {
      bool sw = false;
      if(key == infll) {
        sw = true;
        key = 0;
      }
 
      all = parent.all + key + child.all;
      int64 top = md1.top();
      p_len = max(child.p_len, max(top, parent.p_len) + key + child.all);
      c_len = max(parent.c_len, max(top, child.c_len) + key + parent.all);
      diameter = max({parent.diameter, child.diameter, top + key + md1.top2(), md2.top()});
      diameter = max({diameter, parent.p_len + key + max(child.c_len, top), child.c_len + key + top});
      if(sw) {
        p_len = max(p_len, key + child.all);
        c_len = max(c_len, key + parent.all);
        diameter = max(diameter, max({parent.p_len, child.c_len, top, 0LL}) + key);
      }
 
      if(p_len < -infll2) p_len = -infll;
      if(c_len < -infll2) c_len = -infll;
      if(diameter < -infll2) diameter = -infll;
    }
 
    void add(const Sum &ch) {
      md1.insert(ch.c_len);
      md2.insert(ch.diameter);
    }
 
    void erase(const Sum &ch) {
      md1.erase(ch.c_len);
      md2.erase(ch.diameter);
    }
  } e;
 
 
 
  using LCT = LinkCutTreeSubtree< Sum, Key >;
  LCT lct(e);
  vector< LCT::Node * > vv(N), ee(N);
  for(int i = 0; i < N; i++) {
    vv[i] = lct.make_node(infll);
  }
  auto ff=[&](ll x,ll y){return x+y;};
  auto fs=[&](ll x){return x;};
  LinkCutTree<ll,ll> lce(2*N,ff,fs,0LL);
  for(int i=0;i<2*N;i++)lce.add_vertex(i,0);
  ll n=N;
  ll x0,q;cin>>x0>>q;
  int cnt=0;
  while(q--){
    ll t;cin>>t;
    if(t==1){
      ll v,w;cin>>v>>w;
      lce.update(cnt+n,w);
      lce.add_edge(cnt+n,v);
      lce.add_edge(cnt+n,x0);
      ee[cnt]=lct.make_node(w);
      lct.link(vv[v],ee[cnt]);
      lct.link(ee[cnt],vv[x0]);
      cnt++;
    }
    if(t==2){
      int u,v;cin>>u>>v;
      if(lce.connected(u,v)){
        ll d=lce.val_path(u,v);
        cout<<d<<endl;
        x0+=d;
        x0%=n;
      }
      else{
        cout<<-1<<endl;
      }
    }
    if(t==3){
      int v;cin>>v;
      lct.expose(vv[v]);
      cout<<(vv[v]->sum.diameter)<<endl;
    }
    if(t==4){
      ll ad;cin>>ad;
      x0+=ad;
      x0%=n;
    }
    //cout<<"x:"<<x0<<endl;
  }
} 
0