結果
問題 | No.1787 Do Use Dynamic Tree |
ユーザー |
![]() |
提出日時 | 2021-12-16 23:10:29 |
言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 7,467 ms / 10,000 ms |
コード長 | 18,821 bytes |
コンパイル時間 | 17,504 ms |
コンパイル使用メモリ | 311,328 KB |
最終ジャッジ日時 | 2025-01-26 23:52:22 |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 38 |
ソースコード
#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>=201703Ltemplate<typename T,typename ...Args>auto make_vector(T x,int arg,Args ...args){if constexpr(sizeof...(args)==0)return vector<T>(arg,x);elsereturn 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>=201703Lconstexpr inline long long powll(long long a,long long b){long long res=1;while(b--)res*=a;return res;}#endiftemplate<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;}}