Submission #534805


Source Code Expand

#include <bits/stdc++.h>
using namespace std;
struct SegmentTree{
	int n_;
	vector<int> seg;
	// [1,N]
	SegmentTree(int N){
		n_ = 1;
		while(n_ < N ) n_ *= 2;
		seg.resize(2*n_,2e9); //要設定
	}
	void add(int i,int v){
		i += n_-1;
		seg[i] = v;
		i /= 2;
		while(i){
			seg[i] = min(seg[i*2],seg[i*2+1]); //要設定
			i /= 2;
		}
	}
	void add(int i,int j,int v){
		assert(i == j);
		add(i,v);
	}
	int get(int l,int r,int k,int a,int b){
		if( b < l || r < a ) return 2e9; //要設定
		if( l <= a && b <= r ){
			return seg[k];
		}
		int m = (a+b)/2;
		return min(get(l,r,k*2,a,m),get(l,r,k*2+1,m+1,b)); //要設定
	}
	// x未満の値の最小位置を返す
	int getMinPos(int l,int r,int x,int k,int a,int b){
		if( b < l || r < a ) return -1; //要設定
		if( b == a ){
			return seg[k] < x ? seg[k] : -1;
		}

		int m = (a+b)/2;
		if( get(l,r,k*2,a,m) < x ) return getMinPos(l,r,x,k*2,a,m);
		if( get(l,r,k*2+1,m+1,b) < x ) return getMinPos(l,r,x,k*2+1,m+1,b);
		return -1;
	}
	int getMaxPos(int l,int r,int x,int k,int a,int b){
		if( b < l || r < a ){
			//cout << "[" << a << "," << b << "] [" << l << "," << r << "]" << endl;
			return -1; //要設定
		}
		if( b == a ){
			return seg[k] < x ? seg[k] : -1;
		}
		int m = (a+b)/2;
		
		if( get(l,r,k*2+1,m+1,b) < x ){
		//	cout << "kotti" << endl;
			return getMaxPos(l,r,x,k*2+1,m+1,b);
		}
		if( get(l,r,k*2,a,m) < x ){
			return getMaxPos(l,r,x,k*2,a,m);
		}
		return -1;
	}
	inline int get(int l,int r){
		return get(l,r,1,1,n_);
	}
	inline int getMinPos(int l,int r,int x){
		return getMinPos(l,r,x,1,1,n_);
	}
	inline int getMaxPos(int l,int r,int x){
		return getMaxPos(l,r,x,1,1,n_);
	}
};



struct UnionFind {
  vector<int> data;
  UnionFind(int size) : data(size, -1) { }
  bool unionSet(int x, int y) {
    x = root(x); y = root(y);
    if (x != y) {
      if (data[y] < data[x]) swap(x, y);
      data[x] += data[y]; data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) {
    return root(x) == root(y);
  }
  int root(int x) {
    return data[x] < 0 ? x : data[x] = root(data[x]);
  }
  int size(int x) {
    return -data[root(x)];
  }
};


class Tree{
public:
	//[0,n)
	int n,logn,root;
	vector<vector<int>> child;
	vector<vector<int>> parent;
	vector<pair<int,int>> edges;
	vector<int> depth;
	Tree(int n_,vector<pair<int,int>> es,int root) : root(root){
		edges = es;
		n = n_;
		logn = 0;
		while(n_){
			++logn;
			n_ /= 2;
		}
		parent.resize(logn,vector<int>(n,-1));
		depth.resize(n,-1);
		child.resize(n);
		vector<vector<int>> g(n);
		for( auto e : es ){
			g[e.first].push_back(e.second);
			g[e.second].push_back(e.first);
		}
		dfs(g);
		gen_lca();
		verify();
	}
	bool verify(){
		for(int i = 0 ; i < n ; i++)
			assert( depth[i] != -1 );
	}
	int lca(int x,int y){
		if( depth[x] < depth[y] )swap(x,y);
		int d = depth[x] - depth[y];
		for(int i = 0 ; i < logn ; i++)
			if( d >> i & 1 ) x = parent[i][x];
		if( x == y ) return x;
		
		for(int i = logn-1 ; i >= 0 ; i--){
			if( parent[i][x] != parent[i][y] ){
				x = parent[i][x];
				y = parent[i][y];
			}
		}
		return parent[0][x];
	}
	int distance(int x,int y){
		return depth[x] + depth[y] - 2 * depth[lca(x,y)];
	}
private:
	int gen_lca(){
		for(int i = 1 ; i < logn ; i++){
			for(int j = 0 ; j < n ; j++)
				if( parent[i-1][j] != -1 ) 
					parent[i][j] = parent[i-1][parent[i-1][j]];
		}
	}
	int dfs(const vector<vector<int>> &g){
		stack< array<int,3> > S;
		S.push(array<int,3>{root,-1,0});
		while( S.size() ){
			int x = S.top()[0];
			int p = S.top()[1];
			int d = S.top()[2];
			S.pop();
			parent[0][x] = p;
			depth[x] = d;
			for( auto e : g[x] ){
				if( e != p ){
					S.push(array<int,3>{e,x,d+1});
					child[x].push_back(e);
				}
			}
		}
	}
};

template<class SegmentTree> class HeavyLightDecomp{
public:
	Tree tr;
	vector< pair<int,int> > where; // (id,pos)
	vector< vector<int> > pathSeq;
	vector<SegmentTree> seg;
	HeavyLightDecomp(const Tree &tr) : tr(tr){
		// init
		where.resize(tr.n,{-1,-1});
		vector<int> subtree(tr.n);
		vector<pair<int,int>> sortedIdx;
		for(int i = 0 ; i < tr.n ; i++)
			sortedIdx.push_back({tr.depth[i],i});
		sort(sortedIdx.begin(),sortedIdx.end());
		
		// calc sizes of each subtree
		for(int I = tr.n-1 ; I >= 0 ; I--){
			int i = sortedIdx[I].second;
			subtree[i] = 1;
			for( auto e : tr.child[i] ) subtree[i] += subtree[e];
		}
		// do heavyLightDecomp Part1
		for(int I = 0 ; I < tr.n ; I++){
			int i = sortedIdx[I].second;
			if( where[i].first == -1 ){
				where[i].first = pathSeq.size();
				pathSeq.push_back(vector<int>());
			}
			where[i].second = pathSeq[where[i].first].size();
			pathSeq[where[i].first].push_back(i);
			for( auto e : tr.child[i] ){
				if( 2*subtree[e] > subtree[i] ){
					where[e].first = where[i].first;
				}
			}
		}
		// Set segtrees to each heavy-path.
		for(int i = 0 ; i < pathSeq.size() ; i++){
			int n_ = 1;
			while( n_ < pathSeq[i].size() ) n_ *= 2;
			seg.push_back(SegmentTree(n_));
		}
	}
	//加算点の重複に気をつけて
	void addToVertex(int a,int b,int v){
		int p = tr.lca(a,b);
		add(a,p,v,0); //要設定
		add(b,p,v,0); //要設定
	}
	/*
	int getToVertex(int a,int b){
		int p = tr.lca(a,b);
		return min(get(a,p,0),get(b,p,0)); //要設定
	}
	*/

	inline int upMove(int c,int p,int x){
		int id1 = where[c].first;
		int id2 = where[p].first;
		int l = where[p].second + 1;
		int r = where[c].second + 1;
		int ans = 1145141919;
		if( id1 == id2 ){
			//cout << l << " " << r << " " << x << endl;
			ans = seg[id1].getMaxPos(l,r,x); //要設定
		}else{
			ans = seg[id1].getMaxPos(1,r,x); //要設定
			if( ans == -1 ) ans = upMove(tr.parent[0][pathSeq[id1][0]],p,x);
		}
		return ans;
	}
	inline int downMove(int c,int p,int x){
		int id1 = where[c].first;
		int id2 = where[p].first;
		int l = where[p].second + 1;
		int r = where[c].second + 1;
		int ans = 1145141919;
		if( id1 == id2 ){
			ans = seg[id1].getMinPos(l,r,x); //要設定
		}else{
			int ans2 = downMove(tr.parent[0][pathSeq[id1][0]],p,x);
			if( ans2 != -1 ) ans = ans2;
			else ans = seg[id1].getMinPos(1,r,x); //要設定	
		}
		return ans;
	}
	private: 
	inline void add(int c,int p,int v,int isEdgeQuery){
		int id1 = where[c].first;
		int id2 = where[p].first;
		int l = where[p].second + 1;
		int r = where[c].second + 1;
		if( id1 == id2 ){
			seg[id1].add(l+isEdgeQuery,r,v); //要設定
		}else{
			seg[id1].add(1,r,v); //要設定
			add(tr.parent[0][pathSeq[id1][0]],p,v,isEdgeQuery);
		}
	}
	/*
	inline int get(int c,int p,int isEdgeQuery){
		int id1 = where[c].first;
		int id2 = where[p].first;
		int l = where[p].second + 1;
		int r = where[c].second + 1;
		int ans = 0;
		if( id1 == id2 ){
			ans += seg[id1].get(l+isEdgeQuery,r); //要設定
		}else{
			ans += seg[id1].get(1,r); //要設定
			ans += get(tr.parent[0][pathSeq[id1][0]],p,isEdgeQuery);
		}
		return ans;
	}
	*/

};


int value[100010];

int main(){
	int n,q;
	cin >> n >> q;
	for(int i = 0 ; i < n ; i++) cin >> value[i];

	vector< pair<int,int> > es;
	for(int i = 0 ; i < n-1 ; i++){
		int a,b;
		cin >> a >> b;
		--a,--b;
		es.push_back({a,b});
	}
	Tree tr(n,es,0);
	HeavyLightDecomp<SegmentTree> hl(tr);
	for(int i = 0 ; i < n ; i++)
		hl.addToVertex(i,i,value[i]);
	//for(int i = 0 ; i < n ; i++)
	//	cout << hl.getToVertex(i,i) << endl;
	for(int i = 0 ; i < q ; i++){
		int x,a,b;
		cin >> x >> a >> b;
		--a,--b;
		int p = tr.lca(a,b);
		//cout << x << endl;
		while(1){
			int mVal = hl.upMove(a,p,x+1);
			//cout << x << " " << mVal << endl;
			if( mVal == -1 ){
				break;					
			}else x %= mVal;
		}
		//cout << x << endl;

		while(1){
			//out << a << " "<< b << " vs " << p << endl;
			int mVal = hl.downMove(b,p,x+1);
			//cout << x << " " << mVal << endl;
			if( mVal == -1 ){
				break;					
			}else x %= mVal;
		}


		cout << x << endl;
	}
}
 

Submission Info

Submission Time
Task J - MODクエリ
User kyuridenamida
Language C++11 (GCC 4.9.2)
Score 400
Code Size 8155 Byte
Status AC
Exec Time 1866 ms
Memory 39132 KB

Judge Result

Set Name Small All
Score / Max Score 30 / 30 370 / 370
Status
AC × 16
AC × 38
Set Name Test Cases
Small 00_sample_path_01.txt, 15_path_00.txt, 15_path_01.txt, 15_path_02.txt, 15_path_03.txt, 15_path_04.txt, 16_path_05.txt, 16_path_06.txt, 16_path_07.txt, 16_path_08.txt, 16_path_09.txt, 17_path_10.txt, 17_path_11.txt, 17_path_12.txt, 17_path_13.txt, 17_path_14.txt
All 00_sample_path_01.txt, 15_path_00.txt, 15_path_01.txt, 15_path_02.txt, 15_path_03.txt, 15_path_04.txt, 16_path_05.txt, 16_path_06.txt, 16_path_07.txt, 16_path_08.txt, 16_path_09.txt, 17_path_10.txt, 17_path_11.txt, 17_path_12.txt, 17_path_13.txt, 17_path_14.txt, 20_random_15.txt, 20_random_16.txt, 20_random_17.txt, 21_random_18.txt, 21_random_19.txt, 21_random_20.txt, 30_random_21.txt, 30_random_22.txt, 30_random_23.txt, 40_random_24.txt, 40_random_25.txt, 40_random_26.txt, 49_sample_02.txt, 61_test_27.txt, 61_test_28.txt, 61_test_29.txt, 63_star_30.txt, 63_star_31.txt, 63_star_32.txt, 64_three_33.txt, 64_three_34.txt, 64_three_35.txt
Case Name Status Exec Time Memory
00_sample_path_01.txt AC 27 ms 804 KB
15_path_00.txt AC 27 ms 744 KB
15_path_01.txt AC 26 ms 792 KB
15_path_02.txt AC 25 ms 804 KB
15_path_03.txt AC 26 ms 804 KB
15_path_04.txt AC 27 ms 780 KB
16_path_05.txt AC 28 ms 796 KB
16_path_06.txt AC 26 ms 796 KB
16_path_07.txt AC 28 ms 804 KB
16_path_08.txt AC 26 ms 800 KB
16_path_09.txt AC 25 ms 920 KB
17_path_10.txt AC 1730 ms 31840 KB
17_path_11.txt AC 1754 ms 31840 KB
17_path_12.txt AC 1728 ms 31844 KB
17_path_13.txt AC 1730 ms 31832 KB
17_path_14.txt AC 1760 ms 31840 KB
20_random_15.txt AC 26 ms 924 KB
20_random_16.txt AC 26 ms 928 KB
20_random_17.txt AC 26 ms 928 KB
21_random_18.txt AC 28 ms 924 KB
21_random_19.txt AC 25 ms 800 KB
21_random_20.txt AC 26 ms 772 KB
30_random_21.txt AC 27 ms 928 KB
30_random_22.txt AC 28 ms 804 KB
30_random_23.txt AC 27 ms 808 KB
40_random_24.txt AC 1382 ms 39008 KB
40_random_25.txt AC 1369 ms 39012 KB
40_random_26.txt AC 1412 ms 39132 KB
49_sample_02.txt AC 26 ms 928 KB
61_test_27.txt AC 1269 ms 35040 KB
61_test_28.txt AC 1234 ms 35044 KB
61_test_29.txt AC 1281 ms 35096 KB
63_star_30.txt AC 974 ms 37916 KB
63_star_31.txt AC 962 ms 37852 KB
63_star_32.txt AC 987 ms 37856 KB
64_three_33.txt AC 1771 ms 32472 KB
64_three_34.txt AC 1866 ms 33304 KB
64_three_35.txt AC 1765 ms 32740 KB