結果
問題 | No.1787 Do Use Dynamic Tree |
ユーザー | hotman78 |
提出日時 | 2021-12-16 23:10:29 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 6,760 ms / 10,000 ms |
コード長 | 18,821 bytes |
コンパイル時間 | 4,635 ms |
コンパイル使用メモリ | 254,792 KB |
実行使用メモリ | 75,264 KB |
最終ジャッジ日時 | 2024-09-13 22:43:38 |
合計ジャッジ時間 | 83,831 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 2 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 2 ms
5,376 KB |
testcase_11 | AC | 2 ms
5,376 KB |
testcase_12 | AC | 12 ms
5,376 KB |
testcase_13 | AC | 13 ms
5,376 KB |
testcase_14 | AC | 16 ms
5,376 KB |
testcase_15 | AC | 13 ms
5,376 KB |
testcase_16 | AC | 14 ms
5,376 KB |
testcase_17 | AC | 14 ms
5,376 KB |
testcase_18 | AC | 13 ms
5,376 KB |
testcase_19 | AC | 12 ms
5,376 KB |
testcase_20 | AC | 11 ms
5,376 KB |
testcase_21 | AC | 16 ms
5,376 KB |
testcase_22 | AC | 3,783 ms
43,136 KB |
testcase_23 | AC | 2,814 ms
60,672 KB |
testcase_24 | AC | 3,053 ms
37,504 KB |
testcase_25 | AC | 4,951 ms
65,152 KB |
testcase_26 | AC | 5,004 ms
65,152 KB |
testcase_27 | AC | 4,923 ms
65,152 KB |
testcase_28 | AC | 2,777 ms
75,264 KB |
testcase_29 | AC | 2,840 ms
75,136 KB |
testcase_30 | AC | 2,880 ms
75,136 KB |
testcase_31 | AC | 4,060 ms
75,136 KB |
testcase_32 | AC | 6,260 ms
75,136 KB |
testcase_33 | AC | 6,760 ms
74,880 KB |
testcase_34 | AC | 2,414 ms
75,136 KB |
testcase_35 | AC | 5,989 ms
75,136 KB |
testcase_36 | AC | 6,535 ms
74,880 KB |
testcase_37 | AC | 3,417 ms
75,136 KB |
testcase_38 | AC | 3,422 ms
75,136 KB |
testcase_39 | AC | 3,514 ms
75,136 KB |
ソースコード
#line 2 "cpplib/util/template.hpp" #pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") #pragma GCC target("avx2") #include<bits/stdc++.h> using namespace std; struct __INIT__{__INIT__(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(15);}}__INIT__; typedef long long lint; #define INF (1LL<<60) #define IINF (1<<30) #define EPS (1e-10) #define endl ('\n') typedef vector<lint> vec; typedef vector<vector<lint>> mat; typedef vector<vector<vector<lint>>> mat3; typedef vector<string> svec; typedef vector<vector<string>> smat; template<typename T>using V=vector<T>; template<typename T>using VV=V<V<T>>; template<typename T>inline void output(T t){bool f=0;for(auto i:t){cout<<(f?" ":"")<<i;f=1;}cout<<endl;} template<typename T>inline void output2(T t){for(auto i:t)output(i);} template<typename T>inline void debug(T t){bool f=0;for(auto i:t){cerr<<(f?" ":"")<<i;f=1;}cerr<<endl;} template<typename T>inline void debug2(T t){for(auto i:t)debug(i);} #define loop(n) for(long long _=0;_<(long long)(n);++_) #define _overload4(_1,_2,_3,_4,name,...) name #define __rep(i,a) repi(i,0,a,1) #define _rep(i,a,b) repi(i,a,b,1) #define repi(i,a,b,c) for(long long i=(long long)(a);i<(long long)(b);i+=c) #define rep(...) _overload4(__VA_ARGS__,repi,_rep,__rep)(__VA_ARGS__) #define _overload3_rev(_1,_2,_3,name,...) name #define _rep_rev(i,a) repi_rev(i,0,a) #define repi_rev(i,a,b) for(long long i=(long long)(b)-1;i>=(long long)(a);--i) #define rrep(...) _overload3_rev(__VA_ARGS__,repi_rev,_rep_rev)(__VA_ARGS__) // #define rep(i,...) for(auto i:range(__VA_ARGS__)) // #define rrep(i,...) for(auto i:reversed(range(__VA_ARGS__))) // #define repi(i,a,b) for(lint i=lint(a);i<(lint)(b);++i) // #define rrepi(i,a,b) for(lint i=lint(b)-1;i>=lint(a);--i) // #define irep(i) for(lint i=0;;++i) // inline vector<long long> range(long long n){if(n<=0)return vector<long long>();vector<long long>v(n);iota(v.begin(),v.end(),0LL);return v;} // inline vector<long long> range(long long a,long long b){if(b<=a)return vector<long long>();vector<long long>v(b-a);iota(v.begin(),v.end(),a);return v;} // inline vector<long long> range(long long a,long long b,long long c){if((b-a+c-1)/c<=0)return vector<long long>();vector<long long>v((b-a+c-1)/c);for(int i=0;i<(int)v.size();++i)v[i]=i?v[i-1]+c:a;return v;} // template<typename T>inline T reversed(T v){reverse(v.begin(),v.end());return v;} #define all(n) begin(n),end(n) template<typename T,typename E>bool chmin(T& s,const E& t){bool res=s>t;s=min<T>(s,t);return res;} template<typename T,typename E>bool chmax(T& s,const E& t){bool res=s<t;s=max<T>(s,t);return res;} const string ds="DRUL"; const vector<lint> dx={1,0,-1,0,1,1,-1,-1}; const vector<lint> dy={0,1,0,-1,1,-1,1,-1}; #define SUM(v) accumulate(all(v),0LL) #if __cplusplus>=201703L template<typename T,typename ...Args>auto make_vector(T x,int arg,Args ...args){if constexpr(sizeof...(args)==0)return vector<T>(arg,x);else return vector(arg,make_vector<T>(x,args...));} #endif #define extrep(v,...) for(auto v:__MAKE_MAT__({__VA_ARGS__})) #define bit(n,a) ((n>>a)&1) vector<vector<long long>> __MAKE_MAT__(vector<long long> v){if(v.empty())return vector<vector<long long>>(1,vector<long long>());long long n=v.back();v.pop_back();vector<vector<long long>> ret;vector<vector<long long>> tmp=__MAKE_MAT__(v);for(auto e:tmp)for(long long i=0;i<n;++i){ret.push_back(e);ret.back().push_back(i);}return ret;} using graph=vector<vector<int>>; template<typename T>using graph_w=vector<vector<pair<int,T>>>; template<typename T,typename E>ostream& operator<<(ostream& out,pair<T,E>v){out<<"("<<v.first<<","<<v.second<<")";return out;} #if __cplusplus>=201703L constexpr inline long long powll(long long a,long long b){long long res=1;while(b--)res*=a;return res;} #endif template<typename T,typename E>pair<T,E>& operator+=(pair<T,E>&s,const pair<T,E>&t){s.first+=t.first;s.second+=t.second;return s;} template<typename T,typename E>pair<T,E>& operator-=(pair<T,E>&s,const pair<T,E>&t){s.first-=t.first;s.second-=t.second;return s;} template<typename T,typename E>pair<T,E> operator+(const pair<T,E>&s,const pair<T,E>&t){auto res=s;return res+=t;} template<typename T,typename E>pair<T,E> operator-(const pair<T,E>&s,const pair<T,E>&t){auto res=s;return res-=t;} // 128*1024*1024 #define BEGIN_STACK_EXTEND(size) void * stack_extend_memory_ = malloc(size);void * stack_extend_origin_memory_;char * stack_extend_dummy_memory_ = (char*)alloca((1+(int)(((long long)stack_extend_memory_)&127))*16);*stack_extend_dummy_memory_ = 0;asm volatile("mov %%rsp, %%rbx\nmov %%rax, %%rsp":"=b"(stack_extend_origin_memory_):"a"((char*)stack_extend_memory_+(size)-1024)); #define END_STACK_EXTEND asm volatile("mov %%rax, %%rsp"::"a"(stack_extend_origin_memory_));free(stack_extend_memory_); #line 2 "main.cpp" template<typename T,typename E,typename Compress,typename Rake,typename Rev> class link_cut{ class rake_tree{ struct node; using np=node*; struct node{ unsigned long key,l,r; T val,sum; // E lazy; bool rev=0; int cnt=1,dep=0; static const node* nil; np ch[2]={}; np p=0; node(unsigned long key,T val):key(key),l(key),r(key),val(val),sum(val){} bool is_root() { return !p||(p->ch[0]!=this&&p->ch[1]!=this); } }; Rake rake; T et; np root=nullptr; inline int count(np t){return t?t->cnt:0;} inline int depth(np t){return t?t->dep:0;} np update(np t){ if(!t)return t; t->cnt=count(t->ch[0])+1+count(t->ch[1]); t->dep=max(depth(t->ch[0]),depth(t->ch[1]))+1; t->l=t->ch[0]?t->ch[0]->l:t->l; t->r=t->ch[1]?t->ch[1]->r:t->r; t->sum=rake(rake(t->ch[0]?t->ch[0]->sum:et,t->val),t->ch[1]?t->ch[1]->sum:et); return t; } void rot(np t,bool b){ np x=t->p,y=x->p; if((x->ch[1-b]=t->ch[b]))t->ch[b]->p=x; t->ch[b]=x,x->p=t; update(x);update(t); if((t->p=y)){ if(y->ch[0]==x)y->ch[0]=t; if(y->ch[1]==x)y->ch[1]=t; update(y); } } void push(np t){ // if(t->lazy!=ee){ // if(t->ch[0])propagate(t->ch[0],t->lazy); // if(t->ch[1])propagate(t->ch[1],t->lazy); // t->lazy=ee; // } // if(t->rev){ // if(t->ch[0])toggle(t->ch[0]); // if(t->ch[1])toggle(t->ch[1]); // t->rev=0; // } } np splay(np t){ push(t); while(!t->is_root()){ np q=t->p; if(q->is_root()){ push(q), push(t); rot(t,q->ch[0]==t); }else{ np r=q->p; push(r), push(q), push(t); bool b=r->ch[0]==q; if(q->ch[1-b]==t)rot(q,b),rot(t,b); else rot(t,1-b),rot(t,b); } } return t; } // int lower_bound(T val,np t){ // if(!t)return 0; // bool b=val>t->val; // return(b?count(t->ch[0])+1:0)+lower_bound(val,t->ch[b]); // } // int upper_bound(T val,np t){ // if(!t)return 0; // bool b=val>=t->val; // return(b?count(t->ch[0])+1:0)+upper_bound(val,t->ch[b]); // } // T find_by_order(T idx,np t){ // if(idx==count(t->ch[0]))return t->val; // bool b=idx>count(t->ch[0]); // return find_by_order(idx-(b?count(t->ch[0])+1:0),t->ch[b]); // } public: rake_tree(Rake rake,T et):rake(rake),et(et){} std::pair<np,np> split(np t,unsigned long key){ if(!t)return make_pair(nullptr,nullptr); bool b=key>t->key; auto s=split(t->ch[b],key); if(t->ch[b])t->ch[b]->p=0; t->ch[b]=b?s.first:s.second; if(t->ch[b])t->ch[b]->p=t; return b?make_pair(update(t),s.second):make_pair(s.first,update(t)); } std::pair<np,np> split(unsigned long key){ return split(root,key); } np merge(np s,np t){ if(!s)return t; if(!t)return s; while(s->ch[1])s=s->ch[1]; splay(s);splay(t); s->ch[1]=t; t->p=s; update(s); return s; } void insert(unsigned long key,T val){ auto [s,t]=split(key); root=merge(s,merge(new node(key,val),t)); } void erase(unsigned long key){ auto [s,t]=split(key); while(t->ch[0])t=t->ch[0]; splay(t); assert(t->key==key); if(t->ch[1])t->ch[1]->p=0; root=merge(s,t->ch[1]); delete(t); } rake_tree(T et,Rake rake):et(et),rake(rake){} inline int size(){return count(root);} // inline int count(T val){return upper_bound(val,root)-lower_bound(val,root);} // inline int count(int l,int r){return lower_bound(r,root)-lower_bound(l,root);} // inline T sum(int l,int r){return sum(l,r,root);} inline T all_sum(){return root?root->sum:et;} //0-indexでidx番目 // inline T operator[](T idx){return find_by_order(idx,root);} // //x未満の個数/s[lower_bound(x)]はx以上最小の値 // inline int lower_bound(T x){return lower_bound(x,root);} // //x以下の個数/s[upper_bound(x)]はxより大きい最小の値 // inline int upper_bound(T x){return upper_bound(x,root);} }; public: struct node; using np=node*; struct node{ np ch[2]={}; np p=0; int key; unsigned long id,id_sum,rake_node_id_sum=0; T val,path_sum,subtree_sum,subtree_sum2,subtree_sum_rev,subtree_sum2_rev; rake_tree rake_node; bool rev=0; // E lazy=ee; int sz=1; // node(){} inline unsigned long rnd() { static unsigned long x=123456789, y=362436069, z=521288629, w=88675123; unsigned long t=(x^(x<<11)); x=y; y=z; z=w; return ( w=(w^(w>>19))^(t^(t>>8)) ); } node(unsigned long key,T et,Rake rake):key(key),val(et),path_sum(et),subtree_sum(et),subtree_sum2(et),subtree_sum_rev(et),subtree_sum2_rev(et),rake_node(rake,et){ id=id_sum=rnd(); } bool is_root(){ return !p||(p->ch[0]!=this&&p->ch[1]!=this); } }; std::vector<np>p; Compress compress; Rake rake; Rev rev; T et; E ee; int size(np t){return t?t->sz:0;} void update(np t){ t->sz=size(t->ch[0])+1+size(t->ch[1]); // t->l=t->ch[0]?t->ch[0]->l:t->l; // t->r=t->ch[1]?t->ch[1]->r:t->r; t->id_sum=(t->id^(t->ch[0]?t->ch[0]->id_sum:0)^(t->ch[1]?t->ch[1]->id_sum:0)^(t->rake_node_id_sum)); // subtree_sum は親が t, subtree_sum2 は親がt->ch[0]->ch[0]->... // t->path_sum=compress(t->ch[0]?t->ch[0]->path_sum:et,compress(t->val,t->ch[1]?t->ch[1]->path_sum:et)); t->subtree_sum=compress(t->val,rake(t->rake_node.all_sum(),t->ch[1]?t->ch[1]->subtree_sum2:et)); t->subtree_sum2=compress(t->ch[0]?t->ch[0]->subtree_sum2:et,t->subtree_sum); t->subtree_sum_rev=compress(t->val,rake(t->rake_node.all_sum(),t->ch[0]?t->ch[0]->subtree_sum2_rev:et)); t->subtree_sum2_rev=compress(t->ch[1]?t->ch[1]->subtree_sum2_rev:et,t->subtree_sum_rev); } void rot(np t,bool b){ np x=t->p,y=x->p; push(x), push(t); if((x->ch[1-b]=t->ch[b]))t->ch[b]->p=x; t->ch[b]=x,x->p=t; update(x);update(t); if((t->p=y)){ if(y->ch[0]==x)y->ch[0]=t; if(y->ch[1]==x)y->ch[1]=t; update(y); } } void splay(np t){ push(t); while(!t->is_root()){ np q=t->p; if(q->is_root()){ push(q), push(t); rot(t,q->ch[0]==t); }else{ np r=q->p; push(r), push(q), push(t); bool b=r->ch[0]==q; if(q->ch[1-b]==t)rot(q,b),rot(t,b); else rot(t,1-b),rot(t,b); } } } void propagate(np t,E x){ // t->lazy=h(t->lazy,x); // t->key=g(t->key,x,1); // t->sum=g(t->sum,x,t->sz); } void set_propagate(np t,E x){ expose(t); propagate(t,x); push(t); } void push(np t){ // if(t->lazy!=ee){ // if(t->ch[0])propagate(t->ch[0],t->lazy); // if(t->ch[1])propagate(t->ch[1],t->lazy); // t->lazy=ee; // } if(t->rev){ if(t->ch[0])toggle(t->ch[0]); if(t->ch[1])toggle(t->ch[1]); t->rev=0; } } np expose(np t){ np rp=nullptr; for(np cur=t;cur;cur=cur->p){ splay(cur); if(cur->ch[1]){ // toggle(cur->ch[1]); // push(cur->ch[1]); // cerr<<"+"<<cur->ch[1]->subtree_sum2<<endl; // cerr<<cur->rake_node.all_sum()<<endl; // cerr<<"+"<<cur->ch[1]->id_sum<<endl; cur->rake_node_id_sum^=cur->ch[1]->id_sum; cur->rake_node.insert(cur->ch[1]->id_sum,cur->ch[1]->subtree_sum2); // cerr<<cur->rake_node.all_sum()<<endl; } cur->ch[1]=rp; if(cur->ch[1]){ cur->ch[1]->p=cur; // cerr<<"-"<<cur->ch[1]->subtree_sum2<<endl; // cerr<<cur->rake_node.all_sum()<<endl; // cerr<<"-"<<cur->ch[1]->id_sum<<endl; push(cur->ch[1]); cur->rake_node_id_sum^=cur->ch[1]->id_sum; cur->rake_node.erase(cur->ch[1]->id_sum); // cerr<<cur->rake_node.all_sum()<<endl; } update(cur); rp=cur; } splay(t); return rp; } vector<int>get_path(np x){ vector<int>vs; auto dfs=[&](auto dfs,np cur){ if(!cur)return; dfs(dfs,cur->ch[1]); vs.push_back(cur->key); dfs(dfs,cur->ch[0]); }; expose(x); dfs(dfs,x); return vs; } void link(np ch,np par){ expose(ch); expose(par); ch->p=par; par->ch[1]=ch; update(par); } void cut(np ch){ expose(ch); np par=ch->ch[0]; ch->ch[0]=nullptr; par->p=nullptr; update(ch); } void toggle(np t){ assert(t); swap(t->ch[0],t->ch[1]); swap(t->subtree_sum,t->subtree_sum_rev); swap(t->subtree_sum2,t->subtree_sum2_rev); t->rev^=1; } void evert(np t){ expose(t); toggle(t); push(t); } np get_root(np x){ expose(x); while(x->ch[0]){ push(x); x=x->ch[0]; } return x; } public: link_cut(int sz,Compress comp=Compress(),Rake rake=Rake(),Rev rev=Rev(),T et=T(),E ee=E()):compress(comp),rake(rake),rev(rev),et(et),ee(ee){ p.resize(sz,nullptr); for(int i=0;i<sz;i++)p[i]=new node(i,et,rake); } link_cut(){} void set_val(int t,T val) { expose(p[t]); p[t]->val=val; update(p[t]); } T get_val(int t) { return p[t]->val; } vector<int> get_path(int s,int t){ evert(p[s]); return get_path(p[t]); } void path_add(int s,int t,E x){ evert(p[s]); set_propagate(p[t],x); } T get_path_sum(int s,int t){ evert(p[s]); expose(p[t]); return p[t]->path_sum; } //tを根としたsの部分木の和を得る T get_subtree_sum(int s,int t){ evert(p[t]); expose(p[s]); return p[s]->subtree_sum; } void make_node(T x){ p.emplace_back(new node(p.size(),x)); } void evert(int t){ evert(p[t]); } void link(int s,int t){ evert(p[s]); link(p[s],p[t]); } void cut(int s,int t){ evert(p[s]); cut(p[t]); } bool same(int s,int t){ return get_root(p[s])==get_root(p[t]); } np lca(int s,int t){ if(get_root(p[s])!=get_root(p[t]))return nullptr; expose(p[s]); return expose(p[t]); } }; int main(){ lint n; cin>>n; vec a(n); rep(i,n)a[i]=i; struct data{ bool zero; int pos; int far; // それぞれ l/rの最遠点までのパスにr/lを含むか bool flag; // 通る場合 そのパスにおける r/l の子のノード int ch; }; auto dif=[&](int x){ return x==-1?-1:a[x]; }; auto compress=[&](const data& s,const data& t){ if(s.zero)return t; if(t.zero)return s; data res; if(s.flag&&dif(s.ch)<dif(t.pos)){ res.pos=s.pos; res.far=t.far; res.flag=t.flag; res.ch=t.ch; }else{ res.pos=s.pos; res.far=s.far; res.flag=0; res.ch=-1; } return res; }; auto rake=[&](const data& s,const data& t){ if(s.zero)return t; if(t.zero){ data res=s; res.flag=1; res.ch=s.pos; return res; } if(dif(s.pos)<dif(t.pos)){ return t; } else{ data res=s; res.flag=0; res.ch=-1; return res; } }; auto rev=[&](const data& s){return s;}; const data zero=data{1,0,0,0,0}; link_cut<data,tuple<>,decltype(compress),decltype(rake),decltype(rev)>lc(n,compress,rake,rev,zero); for(int i=0;i<n;++i){ lc.set_val(i,data{0,i,i,1,-1}); } rep(i,n-1){ lint s,t; cin>>s>>t; s--;t--; lc.link(s,t); } lint q; cin>>q; lint pre=0; while(q--){ lint s,t; cin>>s>>t; s--;t--; s=(s+pre)%n; t=(t+pre)%n; // cerr<<s<<" "<<t<<endl; int tmp=a[t]; lc.expose(lc.p[t]); a[t]=a[s]; lc.update(lc.p[t]); lc.expose(lc.p[s]); a[s]=tmp; lc.update(lc.p[s]); // cerr<<lc.p[s].ch[1]<<endl; // cerr<<lc.get_subtree_sum(s,s).far<<lc.get_subtree_sum(s,s).flag<<endl; cout<<(pre=lc.get_subtree_sum(s,s).far+1)<<endl; } }