#line 1 "main.cpp" #define PROBLEM "https://yukicoder.me/problems/no/901" #line 2 "/root/AtCoder/Halc-Library/Template.hpp" //https://tatyam.hatenablog.com/entry/2019/12/15/003634 #include using namespace std; using ll=long long; template using pq=priority_queue,greater>; using pll=pair; const ll LINF=1LL<<60; #define _overload3(_1,_2,_3,name,...) name #define _overload4(_1,_2,_3,_4,name,...) name #define _rep1(i,n) for(ll i=0; i<(n); i++) #define _rep2(i,a,b) for(ll i=(a); i<(b); i++) #define _rep3(i,a,b,c) for(ll i=(a); i<(b); i+=(c)) #define rep(...) _overload4(__VA_ARGS__,_rep3,_rep2,_rep1)(__VA_ARGS__) #define _rrep1(i,n) for(ll i=(n); i-->0;) #define _rrep2(i,a,b) for(ll i=(b); i-->(a);) #define rrep(...) _overload3(__VA_ARGS__,_rrep2,_rrep1)(__VA_ARGS__) #define each(i,...) for(auto&& i:__VA_ARGS__) #define all(i) begin(i),end(i) #define rall(i) rbegin(i),rend(i) template bool chmin(T &a,const T &b){if(a>b){a=b;return true;}else return false;} template bool chmax(T &a,const T &b){if(a ll sum(const T &a){return accumulate(all(a),0LL);} template auto min(const T &a){return *min_element(all(a));} template auto max(const T &a){return *max_element(all(a));} inline int scan(){ return getchar(); } inline void scan(int &a){ scanf("%d", &a); } inline void scan(unsigned &a){ scanf("%u", &a); } inline void scan(long &a){ scanf("%ld", &a); } inline void scan(long long &a){ scanf("%lld", &a); } inline void scan(unsigned long long &a){ scanf("%llu", &a); } inline void scan(char &a){ cin >> a; } inline void scan(float &a){ scanf("%f", &a); } inline void scan(double &a){ scanf("%lf", &a); } inline void scan(long double &a){ scanf("%Lf", &a); } inline void scan(vector &vec){ for(unsigned i = 0; i < vec.size(); i++) { int a; scan(a); vec[i] = a; } } inline void scan(char a[]){ scanf("%s", a); } inline void scan(string &a){ cin >> a; } template inline void scan(vector &vec); template inline void scan(array &vec); template inline void scan(pair &p); template inline void scan(T (&vec)[size]); template inline void scan(vector &vec){ for(auto &i : vec) scan(i); } template inline void scan(deque &vec){ for(auto &i : vec) scan(i); } template inline void scan(array &vec){ for(auto &i : vec) scan(i); } template inline void scan(pair &p){ scan(p.first); scan(p.second); } template inline void scan(T (&vec)[size]){ for(auto &i : vec) scan(i); } template inline void scan(T &a){ cin >> a; } inline void in(){} template inline void in(Head &head, Tail&... tail){ scan(head); in(tail...); } inline void print(){ putchar(' '); } inline void print(const bool &a){ printf("%d", a); } inline void print(const int &a){ printf("%d", a); } inline void print(const unsigned &a){ printf("%u", a); } inline void print(const long &a){ printf("%ld", a); } inline void print(const long long &a){ printf("%lld", a); } inline void print(const unsigned long long &a){ printf("%llu", a); } inline void print(const char &a){ printf("%c", a); } inline void print(const char a[]){ printf("%s", a); } inline void print(const float &a){ printf("%.15f", a); } inline void print(const double &a){ printf("%.15f", a); } inline void print(const long double &a){ printf("%.15Lf", a); } inline void print(const string &a){ for(auto&& i : a) print(i); } template inline void print(const vector &vec); template inline void print(const array &vec); template inline void print(const pair &p); template inline void print(const T (&vec)[size]); template inline void print(const vector &vec){ if(vec.empty()) return; print(vec[0]); for(auto i = vec.begin(); ++i != vec.end(); ){ putchar(' '); print(*i); } } template inline void print(const deque &vec){ if(vec.empty()) return; print(vec[0]); for(auto i = vec.begin(); ++i != vec.end(); ){ putchar(' '); print(*i); } } template inline void print(const array &vec){ print(vec[0]); for(auto i = vec.begin(); ++i != vec.end(); ){ putchar(' '); print(*i); } } template inline void print(const pair &p){ print(p.first); putchar(' '); print(p.second); } template inline void print(const T (&vec)[size]){ print(vec[0]); for(auto i = vec; ++i != end(vec); ){ putchar(' '); print(*i); } } template inline void print(const T &a){ cout << a; } inline int out(){ putchar('\n'); return 0; } template inline int out(const T &t){ print(t); putchar('\n'); return 0; } template inline int out(const Head &head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; } using ld=long double; using ull=unsigned long long; using uint=unsigned int; using pii=pair; using pdd=pair; using tuplis=array; #define vec(type,name,...) vector name(__VA_ARGS__); #define vv(type,name,h,...)vector> name(h,vector(__VA_ARGS__)); #define INT(...) int __VA_ARGS__; in(__VA_ARGS__) #define LL(...) ll __VA_ARGS__; in(__VA_ARGS__) #define ULL(...) ull __VA_ARGS__; in(__VA_ARGS__) #define STR(...) string __VA_ARGS__; in(__VA_ARGS__) #define CHR(...) char __VA_ARGS__; in(__VA_ARGS__) #define LD(...) ld __VA_ARGS__; in(__VA_ARGS__) #define VEC(type,name,size) vector name(size); in(name) #define VV(type, name, h, w) vector> name(h, vector(w)); in(name) template ld dsum(const T &a){return accumulate(all(a),0.0L);} const int INF=INT_MAX>>1; const ll MINF=1LL<<40; const ld DINF=numeric_limits::infinity(); const int MODD=1000000007; const int MOD=998244353; const ld EPS=1e-9; const ld PI=3.1415926535897932; const ll four[]={0,1,0,-1,0}; const ll eight[]={0,1,1,0,-1,-1,1,-1,0}; ll intpow(ll a,ll b){ll ret=1;while(b){if(b&1)ret*=a;a*=a;b>>=1;}return ret;} int Yes(bool i=true){return out(i?"Yes":"No");} int No(bool i=true){return out(i?"No":"Yes");} #define len(x) ((int)(x).size()) #define fi first #define se second #line 2 "/root/AtCoder/Halc-Library/Tree/StaticTopTree.hpp" template struct StaticTopTree{ using point=M::point; using path=M::path; struct Node{ bool is_path; point point_val; path path_val; int32_t pos; int32_t left; int32_t right; int32_t parent; Node(bool pat,int32_t po=-1,int32_t lf=-1,int32_t ri=-1){ is_path=pat; pos=po; left=lf; right=ri; parent=-1; } }; size_t sz; vector> tree; vector node_pos; vector nodes; int32_t rt; StaticTopTree(size_t size){ sz=size; tree.resize(sz); node_pos.resize(sz); } void add_edge(int32_t s,int32_t v){ tree[s].emplace_back(v); tree[v].emplace_back(s); } int32_t _path_cluster(int32_t pos,vector &tree_sz){ if(tree[pos].empty()){ node_pos[pos]=nodes.size(); nodes.push_back(Node(1,pos)); _calc_val(nodes.size()-1); return nodes.size()-1; } vector address; vector sizes; while(!tree[pos].empty()){ int32_t max_size=-1; int32_t next_pos=-1; for(int i=0; imax_size){ max_size=tree_sz[tree[pos][i]]; next_pos=i; } } swap(tree[pos][next_pos],tree[pos].back()); next_pos=tree[pos].back(); tree[pos].pop_back(); tree_sz[pos]-=tree_sz[next_pos]; sizes.push_back(tree_sz[pos]); address.push_back(_point_cluster(pos,tree_sz)); pos=next_pos; } address.push_back(_point_cluster(pos,tree_sz)); sizes.push_back(tree_sz[pos]); return _merge(address,sizes,0,address.size(),1); } int32_t _point_cluster(int32_t pos,vector &tree_sz){ if(tree[pos].empty()){ node_pos[pos]=nodes.size(); nodes.push_back(Node(1,pos)); _calc_val(nodes.size()-1); return nodes.size()-1; } vector address; vector sizes; for(int32_t i:tree[pos]){ sizes.push_back(tree_sz[i]); int32_t vert=_path_cluster(i,tree_sz); nodes.push_back(Node(0,-1,vert)); nodes[vert].parent=nodes.size()-1; address.push_back(nodes.size()-1); _calc_val(nodes.size()-1); } int32_t vert=_merge(address,sizes,0,address.size(),0); node_pos[pos]=nodes.size(); nodes.push_back(Node(1,pos,vert)); nodes[vert].parent=nodes.size()-1; _calc_val(nodes.size()-1); return nodes.size()-1; } int32_t _merge(vector &address,vector &sizes,int32_t lf,int32_t ri,bool pat){ if(lf+1==ri)return address[lf]; int32_t add=0; for(int32_t i=lf; iadd-now){ if(now+now-add>bef)i--; int32_t left=_merge(address,sizes,lf,i+1,pat); int32_t right=_merge(address,sizes,i+1,ri,pat); nodes.push_back(Node(pat,-1,left,right)); nodes[left].parent=nodes.size()-1; nodes[right].parent=nodes.size()-1; _calc_val(nodes.size()-1); return nodes.size()-1; } bef=add-now-now; } assert(false); } void _calc_val(int32_t pos){ if(nodes[pos].is_path){ if((nodes[pos].left==-1) && (nodes[pos].right==-1)){ nodes[pos].path_val=M::vertex(nodes[pos].pos); } else if((nodes[pos].left!=-1) && (nodes[pos].right!=-1)){ nodes[pos].path_val=M::compress(nodes[nodes[pos].left].path_val,nodes[nodes[pos].right].path_val); } else{ nodes[pos].path_val=M::add_vertex(nodes[nodes[pos].left].point_val,nodes[pos].pos); } } else{ if((nodes[pos].left!=-1) && (nodes[pos].right!=-1)){ nodes[pos].point_val=M::rake(nodes[nodes[pos].left].point_val,nodes[nodes[pos].right].point_val); } else{ nodes[pos].point_val=M::add_edge(nodes[nodes[pos].left].path_val); } } } void build(int32_t root){ vector vert(sz); vector tree_sz(sz,-1); vert[0]=root; tree_sz[0]=0; int32_t cnt=1; for(int32_t i=0; i=0; i--){ int32_t parent=0; for(int32_t j:tree[vert[i]]){ if(tree_sz[j]==0){ parent=-parent-1; } if(parent>=0)parent++; tree_sz[vert[i]]+=tree_sz[j]; } if(parent<0){ swap(tree[vert[i]][-parent-1],tree[vert[i]].back()); tree[vert[i]].pop_back(); } tree_sz[vert[i]]++; } rt=_path_cluster(root,tree_sz); } path root_value(){ return nodes[rt].path_val; } void calc(int32_t pos){ int32_t change=node_pos[pos]; while(nodes[change].parent!=-1){ _calc_val(change); change=nodes[change].parent; } _calc_val(change); } size_t size(){ return sz; } }; #line 4 "main.cpp" vector mark; vector weight; struct steiner{ using point=array; using path=array; static path vertex(int v){ if(mark[v]){ return {1,0,0,0,0,weight[v]}; } return {0,0,0,0,0,weight[v]}; } static path compress(path p,path c){ if(p[0]==0 && c[0]==0){ return {0,0,0,p[3]+c[3]+c[5],p[3]+c[3]+c[5],p[5]}; } if(p[0]==1 && c[0]==0){ return {1,p[1],p[2],p[3],p[4]+c[3]+c[5],p[5]}; } if(p[0]==0 && c[0]==1){ return {1,c[1],c[2],p[3]+c[3]+c[5],c[4],p[5]}; } return {1,p[2]+c[2]+p[4]+c[3]+c[5],p[2]+c[2]+p[4]+c[3]+c[5],p[3],c[4],p[5]}; } static path add_vertex(point t,int v){ if(t[0]==0){ if(mark[v]){ return {1,0,0,0,0,weight[v]}; } return {0,0,0,0,0,weight[v]}; } if(t[3]==0){ if(mark[v]){ return {1,t[2]+t[4],t[2]+t[4],0,0,weight[v]}; } return {1,t[1],t[2]+t[4],0,0,weight[v]}; } return {1,t[2]+t[4],t[2]+t[4],0,0,weight[v]}; } static point rake(point x,point y){ if(x[0] tree(N); vv(pll,gr,N); rep(i,N-1){ LL(u,v,w); tree.add_edge(u,v); gr[u].push_back(pll(v,w)); gr[v].push_back(pll(u,w)); } mark.resize(N,0); weight.resize(N,-1); weight[0]=0; stack vert; vert.push(0); while(!vert.empty()){ ll pos=vert.top(); vert.pop(); for(auto &[t,w]:gr[pos]){ if(weight[t]==-1){ weight[t]=w; vert.push(t); } } } tree.build(0); LL(Q); rep(i,Q){ LL(k); VEC(ll,x,k); each(j,x){ mark[j]=1; tree.calc(j); } out(tree.root_value()[1]); each(j,x){ mark[j]=0; tree.calc(j); } } } int main(){ solve(); return 0; }