結果

問題 No.235 めぐるはめぐる (5)
ユーザー kuuso1kuuso1
提出日時 2016-07-18 22:45:18
言語 C#(csc)
(csc 3.9.0)
結果
AC  
実行時間 1,846 ms / 10,000 ms
コード長 11,190 bytes
コンパイル時間 4,466 ms
コンパイル使用メモリ 111,360 KB
実行使用メモリ 159,544 KB
最終ジャッジ日時 2024-10-15 17:06:47
合計ジャッジ時間 10,907 ms
ジャッジサーバーID
(参考情報)
judge4 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1,846 ms
132,052 KB
testcase_01 AC 1,406 ms
159,544 KB
testcase_02 AC 1,722 ms
139,552 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
Microsoft (R) Visual C# Compiler version 3.9.0-6.21124.20 (db94f4cc)
Copyright (C) Microsoft Corporation. All rights reserved.

ソースコード

diff #

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

class TEST{
	static void Main(){
		Sol mySol = new Sol();
		mySol.Solve();
	}
}

class Sol{	
	
	public void Solve(){
		
		
		root = 0;
		lca_init();
		nNode = new int[N];
		dfs_cnt();
		EHeavy = new int[N];
		for(int i=0;i<N;i++) EHeavy[i] = -1;
		Compo = new int[N];
		Idx = new int[N];
		HLDec = new List<List<int>>();
		dfs_HLDec();
		
		int NHL=HLDec.Count;
		
		long[][] sVal = new long[NHL][];
		long[][] sSum = new long[NHL][];
		for(int i=0;i<NHL;i++){
			sVal[i] = new long[HLDec[i].Count];
			sSum[i] = new long[HLDec[i].Count+1];
		}
		for(int i=0;i<N;i++){
			sVal[Compo[i]][Idx[i]] = S[i];
		}
		for(int i=0;i<NHL;i++){
			sSum[i][1] = sVal[i][0];
			for(int j=1;j<sVal[i].Length;j++){
				sSum[i][j+1] = sSum[i][j] + sVal[i][j];
				if(sSum[i][j+1] >= mod) sSum[i][j+1] %= mod;
			}
		}
		
		SegTree[] ST=new SegTree[NHL];
		for(int i=0;i<NHL;i++){
			ST[i] = new SegTree(HLDec[i].Count);
		}
		
		for(int i=0;i<N;i++){
			var st = ST[Compo[i]];
			int pos = Idx[i];
			st.Update(pos, C[i]);
		}
		
		StringBuilder sb=new StringBuilder();
		
		foreach(var qr in Query){
			if(qr[0] == 0){
				int a = qr[1];
				int b = qr[2];
				long z = qr[3];
				int c = lca(a,b);
				
				while(Compo[a] != Compo[c]){
					ST[Compo[a]].AddRange(0,Idx[a]+1,z,0,0,ST[Compo[a]].n);
					a = HLDec[Compo[a]][0];
					a = parent[0][a];
				}
				while(Compo[b] != Compo[c]){
					ST[Compo[b]].AddRange(0,Idx[b]+1,z,0,0,ST[Compo[b]].n);
					b = HLDec[Compo[b]][0];
					b = parent[0][b];
				}
				
				if(Idx[b] < Idx[a]){
					int tmp = a; a = b; b = tmp;
				}
				
				ST[Compo[c]].AddRange(Idx[a],Idx[b]+1,z,0,0,ST[Compo[c]].n);
			}
			if(qr[0] == 1){		
				int a = qr[1];
				int b = qr[2];
				int c = lca(a,b);
				long sum = 0;
				
				while(Compo[a] != Compo[c]){
					sum += ST[Compo[a]].QuerySum(0,Idx[a]+1);
					if(sum >= mod) sum -= mod;
					sum += sSum[Compo[a]][Idx[a]+1] - sSum[Compo[a]][0] + mod;
					while(sum >= mod) sum -= mod;
					
					a = HLDec[Compo[a]][0];
					a = parent[0][a];
				}
				while(Compo[b] != Compo[c]){
					sum += ST[Compo[b]].QuerySum(0,Idx[b]+1);
					if(sum >= mod) sum -= mod;
					sum += sSum[Compo[b]][Idx[b]+1] - sSum[Compo[b]][0] + mod;
					while(sum >= mod) sum -= mod;
					b = HLDec[Compo[b]][0];
					b = parent[0][b];
				}
				
				if(Idx[b] < Idx[a]){
					int tmp = a; a = b; b = tmp;
				}
				
				sum += ST[Compo[c]].QuerySum(Idx[a],Idx[b]+1);
				if(sum >= mod) sum -= mod;
				sum += sSum[Compo[c]][Idx[b]+1] - sSum[Compo[c]][Idx[a]] + mod;
				while(sum >= mod) sum -= mod;
				
				sb.AppendLine(sum.ToString());
			}
		}
		Console.Write(sb.ToString());
	}
	
	
	
	
	int N;
	long[] S,C;
	List<int>[] E;
	int Q;
	List<int>[] Query;
	static long mod = (long)1e9+7;
	
	int[][] parent;
	int[] depth;
	static int lmax=24;
	int root;
	
	int[] nNode;
	int[] EHeavy;
	int[] Compo;
	int[] Idx;
	//int cmp;
	List<List<int>> HLDec;
	
	struct Triple{
		public int node,compo,idx;
		public Triple(int n_,int c_,int i_){
			node=n_;compo=c_;idx=i_;
		}
	}
	void dfs_HLDec(){
//Console.WriteLine("now={0},cmp={1},idx={2}",now,cmp,idx);
		
		Stack<Triple> Stk=new Stack<Triple>();
		Stk.Push(new Triple(root,0,0));
		Compo[0]=0;
		Idx[0]=0;
		HLDec.Add(new List<int>());
		HLDec[0].Add(0);
		//cmp=1;
		
		while(Stk.Count>0){
			var p=Stk.Pop();
			int now=p.node;
			int c=p.compo;
			int idx=p.idx;
//Console.WriteLine(now+" "+c+" "+idx);			
			int max=0;int trgt=-1;
			foreach(var nxt in E[now]){
				if(nxt==parent[0][now])continue;
				if(max<nNode[nxt]){
					trgt=nxt;
					max=nNode[nxt];
				}
			}
			if(trgt!=-1){
				EHeavy[now]=trgt;
			}
			foreach(var nxt in E[now]){
				if(nxt!=parent[0][now] && nxt!=EHeavy[now]){
					HLDec.Add(new List<int>());
					Compo[nxt]=HLDec.Count-1;
					Idx[nxt]=0;
					HLDec[Compo[nxt]].Add(nxt);
					Stk.Push(new Triple(nxt,Compo[nxt],0));
				}
				if(nxt==EHeavy[now]){
					Compo[nxt]=c;
					Idx[nxt]=idx+1;
					HLDec[Compo[nxt]].Add(nxt);
					Stk.Push(new Triple(nxt,c,idx+1));
				}
			}
		}
	}		
	
	class Pair{
		public int node,depth;
		public Pair(int n_,int d_){
			node=n_;depth=d_;
		}
	}
	void dfs_cnt(){
		Pair[] P=new Pair[N];
		for(int i=0;i<N;i++){
			P[i]=new Pair(i,depth[i]);
		}
		Array.Sort(P,(x,y)=>x.depth>y.depth?-1:x.depth<y.depth?1:0);
		for(int i=0;i<N;i++){
			nNode[P[i].node]++;
			if(P[i].node!=root)nNode[parent[0][P[i].node]]+=nNode[P[i].node];
		}
	}
	
	void lca_init(){
		parent=new int[lmax][];
		for(int i=0;i<lmax;i++){
			parent[i]=new int[N];
		}
		depth=new int[N];
		
		//root=0;
		//dfs(root,-1,0);//dfs
		bfs(root,0);//bfs
		
		for(int i=0;i<lmax-1;i++){
			for(int j=0;j<N;j++){
				if(parent[i][j]<0){
					parent[i+1][j]=-1;
				}else{
					parent[i+1][j]=parent[i][parent[i][j]];
				}
			}
		}
		
	}
	
	int lca(int u,int v){
		if(depth[u]>depth[v])return lca(v,u);
		for(int i=0;i<lmax;i++){
			if( (((depth[v]-depth[u])>>i)&1) >0 ){
				v=parent[i][v];
			}
		}
		if(u==v)return u;
		for(int i=lmax-1;i>=0;i--){
			if(parent[i][u]!=parent[i][v]){
				u=parent[i][u];
				v=parent[i][v];
			}
		}
		return parent[0][u];
	}
	
	void bfs(int strt,int dep_strt){
		Queue<int> Q=new Queue<int>();
		parent[0][strt]=-1;depth[strt]=0;
		Q.Enqueue(strt);
		while(Q.Count>0){
			int now=Q.Dequeue();
			int par=parent[0][now];
			foreach(int v in E[now]){
				if(v!=par){
					parent[0][v]=now;depth[v]=depth[now]+1;
					Q.Enqueue(v);
				}
			}
		}
	}
	
	
	public Sol(){
		using (var r = new FastIn(100000)){
			N = r.ReadInt();
			S = new long[N];
			for(int i=0;i<N;i++){
				S[i] = r.ReadLong();
			}
			C = new long[N];
			for(int i=0;i<N;i++){
				C[i] = r.ReadLong();
			}
			E = new List<int>[N];
			for(int i=0;i<N;i++){
				E[i] = new List<int>();
			}
			for(int i=0;i<N-1;i++){
				int a = r.ReadInt()-1;
				int b = r.ReadInt()-1;
				E[a].Add(b);
				E[b].Add(a);
			}
			Q = r.ReadInt();
			Query = new List<int>[Q];
			for(int i=0;i<Q;i++){
				Query[i] = new List<int>(4);
				Query[i].Add(r.ReadInt());
				Query[i].Add(r.ReadInt()-1);
				Query[i].Add(r.ReadInt()-1);
				if(Query[i][0] == 0){
					Query[i].Add(r.ReadInt());
				}
			}
		}
	}
	
	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}


class SegTree{
	//segment Tree 
	// 0-origin
	long[] Data;	//
	long[] Lazy;
	long[] Coef;
	long Inf;	//largeNumber
	int N;		//size 
	public int n;		//size (2)
	static long mod = (long)1e9+7;
	
	public SegTree(int n_){
		N=n_;Inf=0;
		n=1;
		while(n<n_)n*=2;
		Data=new long[2*n-1];
		for(int i=0;i<2*n-1;i++)Data[i]=0;
		Lazy=new long[2*n-1];
		for(int i=0;i<2*n-1;i++)Lazy[i]=0;
		Coef=new long[2*n-1];
		for(int i=0;i<2*n-1;i++)Coef[i]=0;
	}
	
	//k-a(Min
	//	   0
	//	 1   2
	//	3 4 5 6
	public void Update(int k,long c){
		k+=n-1;	//n-1
		Coef[k] = c;
		while(k>0){
			k=(k-1)/2;
			Coef[k] = Coef[k*2+1] + Coef[k*2+2];
			if(Coef[k] >= mod) Coef[k] -= mod;
		}
	}
	
	//RMQ;
	//	[a,b) Max
	//	3	k,l,rk- [l,r) 
	//	 Query(a,b,0,0,n) 
	public long Query(int a,int b,int k,int l,int r){
		// [a,b)  [l,r) =Inf
		if(r<=a || b<=l) return Inf;
		// [a,b)  [l,r) Data[k] 
		if(a<=l && r<=b)return Data[k];
		// 
		long vl=Query(a,b,k*2+1,l,(l+r)/2);
		long vr=Query(a,b,k*2+2,(l+r)/2,r);
		return vl + vr;
	}
	
	public long QuerySum(int a,int b){
		QuerySumRet = 0;
		
		QueryWithLazy(a,b,0,0,n);
		
		return QuerySumRet;
	}
	long QuerySumRet;
	
	
	public long QueryWithLazy(int a,int b,int k,int l,int r){
//Console.WriteLine("in query:a={0},b={1},k={2},l={3},r={4}",a,b,k,l,r);
		// [a,b)  [l,r) =Inf
		if(r<=a || b<=l) return Inf;
		// [a,b)  [l,r) Data[k] 
		if(a<=l && r<=b){
			long inc = Coef[k] * Lazy[k] + Data[k];
			if(inc >= mod) inc %= mod;
			QuerySumRet += inc;
			if(QuerySumRet >= mod) QuerySumRet -= mod;
			return Coef[k];
		}
		 
		long cl=QueryWithLazy(a,b,k*2+1,l,(l+r)/2);
		long cr=QueryWithLazy(a,b,k*2+2,(l+r)/2,r);
		long clr = cl + cr;
		long ret = Lazy[k] * clr;
		if(ret >= mod) ret %= mod;
		QuerySumRet += ret;
		if(QuerySumRet >= mod) QuerySumRet -= mod;
		return clr;
	}
	public void AddRange(int a,int b,long val,int k,int l,int r){
		// [a,b)  [l,r) Data[k]+val
		if(r<=a || b<=l) return;
		if(a<=l && r<=b){
			Lazy[k] += val;
			if(Lazy[k] >= mod) Lazy[k] -= mod;
			long inc = val * Coef[k];
			if(inc >= mod) inc %= mod;
			while(k>0){
				k=(k-1)/2;
				Data[k] += inc;
				if(Data[k] >= mod) Data[k] -= mod;
			}
			return;
		}
		AddRange(a,b,val,k*2+1,l,(l+r)/2);
		AddRange(a,b,val,k*2+2,(l+r)/2,r);
	}
	
	public void UniqInit(int val){
		for(int i=0+n-1;i<N+n-1;i++)Data[i]=val;
		int l=n-1;int r=N+n-1-1;
		while(l>0){
			l=(l-1)/2;r=(r-1)/2;
			for(int i=l;i<=r;i++)Data[i]=val;
		}
	}
	
	public void Dump(){
		Console.WriteLine();
		int h=0;
		int cnt=0;
		for(int i=0;i<Data.Length;i++){
			Console.Write("{0} ",Data[i]);
			cnt++;
			if(cnt==1<<h){
				cnt=0;
				h++;
				Console.WriteLine();
			}
		}
		Console.WriteLine();
		h=0;
		cnt=0;
		for(int i=0;i<Data.Length;i++){
			Console.Write("{0} ",Lazy[i]);
			cnt++;
			if(cnt==1<<h){
				cnt=0;
				h++;
				Console.WriteLine();
			}
		}
	}
}


class FastIn:IDisposable {
	int Size;
	byte[] Mem;
	int ptr;
	int rsize;
	bool unfinished;
	Stream stdin;
	void Init(int n) {
		Size = n;
		Mem = new byte[Size];
		rsize=(stdin=Console.OpenStandardInput()).Read(Mem, 0, Size);
		ptr = 0;
		unfinished=(rsize == Size);
	}
	void Next() {
		if (unfinished == false) return;
		rsize=stdin.Read(Mem, 0, Size);
		ptr = 0;
		unfinished = (rsize == Size);
	}
	
	~FastIn(){
		stdin.Dispose();
	}
	void IDisposable.Dispose(){
		stdin.Dispose();
	}
	public void Dispose(){
		stdin.Dispose();
	}
	
	public FastIn() {
		Init(100000);
	}
	public FastIn(int n) {
		Init(n);
	}
	public int ReadInt() {
		int ret = 0;
		int sig = 1;
		while (ptr < rsize && Mem[ptr] != ' ' && Mem[ptr] != '\n' && Mem[ptr] != '\r' ) {
			if(ret==0 && Mem[ptr] == '-'){
				sig *= -1; ptr++; continue;
			}
			ret = ret * 10 + Mem[ptr++] - '0';
			if (ptr == Size) Next();
		}
		while (ptr < rsize && (Mem[ptr] == ' ' || Mem[ptr] == '\n' || Mem[ptr] == '\r') ) {
			ptr++;
			if (ptr == Size) Next();
		}
		return ret*sig;
	}
	public long ReadLong() {
		long ret = 0;
		long sig = 1;
		while (ptr < rsize && Mem[ptr] != ' ' && Mem[ptr] != '\n' && Mem[ptr] != '\r' ) {
			if(ret==0 && Mem[ptr] == '-'){
				sig *= -1; ptr++; continue;
			}
			ret = ret * 10 + Mem[ptr++] - '0';
			if (ptr == Size) Next();
		}
		while (ptr < rsize &&  (Mem[ptr] == ' ' || Mem[ptr] == '\n' || Mem[ptr] == '\r')  ) {
			ptr++;
			if (ptr == Size) Next();
		}
		return ret*sig;
	}
}
0