結果

問題 No.399 動的な領主
ユーザー btkbtk
提出日時 2016-07-15 13:31:22
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
MLE  
実行時間 -
コード長 4,637 bytes
コンパイル時間 2,488 ms
コンパイル使用メモリ 182,092 KB
実行使用メモリ 814,484 KB
最終ジャッジ日時 2024-04-23 01:48:56
合計ジャッジ時間 5,377 ms
ジャッジサーバーID
(参考情報)
judge2 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,940 KB
testcase_02 MLE -
testcase_03 -- -
testcase_04 -- -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include<bits/stdc++.h>
 
using namespace std;
typedef long long LL;
typedef vector<int> V;
typedef vector<V> Graph;
 
struct INIT{INIT(){ios::sync_with_stdio(false);cin.tie(0);}}init;

//heavy light decomposition
namespace hld{
    #define SZ 120000
    int mem[5][SZ];
};
class HLD{
private:
    int *treesize;
    Graph *tree;
public:
    int size,*group,*id,*par,*bg;
private:
    void setTreeSize(int v){
	treesize[v]=1;
	for(auto &u:(*tree)[v]){
	    setTreeSize(u);
	    treesize[v]+=treesize[u];
	}
    }
    void build(int v,int g,int& i){
	group[v]=g;
	id[v]=i++;
	Graph &gr=(*tree);
	const int sz=gr[v].size();
	if(sz){
	    int h=gr[v][0];
	    for(auto &u:gr[v])
		if(treesize[h]<treesize[u])h=u;
	    build(h,g,i);
	    for(auto &u:gr[v])
		if(h!=u){
		    par[size]=id[v];
		    bg[size]=i;
		    build(u,size++,i);
		}
	}
    }
public:
    HLD(Graph *tree,int root=0)
	:treesize(hld::mem[0]),
	 tree(tree),size(0),
	 group(hld::mem[1]),
	 id(hld::mem[2]),
	 par(hld::mem[3]),
	 bg(hld::mem[4])
    {
	setTreeSize(root);
	int i=0;
	par[size]=-1;
	bg[size]=i;
	build(root,size++,i);
    }
    using P=pair<int,int>;
    vector<P> decomposition(int r,int c){
	vector<P> res;
	while(group[c]!=group[r]){
	    res.push_back(P(bg[group[c]],id[c]));
	    c=par[group[c]];
	}
	res.push_back(P(id[r],id[c]));
	return res;
    }
};

void make_tree(int v,Graph& G,V& Par,V& D, Graph& C){
    for(auto &e:G[v]){
	if(e!=Par[v]){
	    C[v].push_back(e);
	    D[e]=D[v]+1;
	    Par[e]=v;
	    make_tree(e,G,Par,D,C);
	}
    }
}


//lcaの準備
void build_PP(V& P,vector<V>& PP){
    int N = P.size();
    for(int i = 0; i < N; i++)PP[0][i] = P[i];
    for(int k = 0,f=1;f; k++){
	f=0;
	for(int i = 0; i < N; i++){
	    if(PP[k][i]<0)PP[k+1][i]=-1;
	    else {PP[k+1][i]=PP[k][PP[k][i]];f=1;}
	}
    }
}
int lca(int u,int v,V& D,vector<V> &PP){
    if(D[u] > D[v])swap(u,v);
    for(int k = 0,d;(d=D[v]-D[u]); k++)if((d >> k) & 1)v=PP[k][v];
    if(u==v)return v;
    for(int k = PP.size() - 1; k >=0 ; k--){
        if(PP[k][u]!=PP[k][v]){
            u=PP[k][u];
            v=PP[k][v];
        }
    }
    return PP[0][u];
}


#define SIZE 1000000
#define L(v) (v*2+1)
#define R(v) (v*2+2)
#define SET 0
#define ADD 1
#define GET 2
typedef LL val;
struct node{
    int bg,ed;
    val v,add;
    inline val getval(){
	return v+(1+ed-bg)*add;
    }
    inline void init(int b,int e){
	bg =b,ed=e;
	v=0,add=0;
    }
    bool isleaf(){return bg==ed;}
}mem[SIZE];
inline val comb(val l,val r){
    return l+r;
}
class segTree{
private:
    node *t;
    void make_tree(int bg,int ed,int v=0){
	node *p=t+v;
	p->init(bg,ed);
	if(!p->isleaf()){
	    int m=(bg+ed)/2;
	    make_tree(bg,m,L(v));
	    make_tree(m+1,ed,R(v));
	}
    }
public:
    using P=pair<int,int>;
    segTree(int bg,int ed):t(mem){make_tree(bg,ed);}
    inline void lazy_update(int v){
	node *p=t+v,*l=t+L(v),*r=t+R(v);
	if(p->isleaf())return;
	l->add+=p->add;
	r->add+=p->add;
	p->add=0;
    }
    inline void update(int v){
	node *p=t+v,*l=t+L(v),*r=t+R(v);
	if(p->isleaf()){
	    p->v+=p->add;
	    p->add=0;
	}
	else{
	    p->v=comb(l->getval(),r->getval());
	}
    }
    val treat(int type,int bg,int ed,val x,int v=0){
	node *p=t+v,*l=t+L(v),*r=t+R(v);
	lazy_update(v);
	if(P(bg,ed)==P(p->bg,p->ed)){
	    if(type==ADD)p->add+=x;
	    update(v);
	    return p->getval();
	}
	int m;
	val res=0;
	if(bg<=(m=min(ed,l->ed)))
	    res=comb(res,treat(type,bg,m,x,L(v)));
	if((m=max(bg,r->bg))<=ed)
	    res=comb(res,treat(type,m,ed,x,R(v)));
	update(v);
	return res;
    }
    val get(int bg,int ed){
	return treat(GET,bg,ed,val());
    }
    val add(int bg,int ed,val x){
	//	cout<<"add:"<<bg<<","<<ed<<endl;
	return treat(ADD,bg,ed,x);
    }
};

int main(){
    int N;
    cin>>N;
    Graph g(N+1),child(N+1);
    V depth(N+1,0),par(N+1,-1);
    vector<V> parpar(20,V(N+1,-1));
    g[0].push_back(1);
    for(int i=1;i<N;i++){
	int u,v;
	cin>>u>>v;
	g[u].push_back(v);
	g[v].push_back(u);
    }
    make_tree(0,g,par,depth,child);
    build_PP(par,parpar);
    HLD h(&child);
    segTree st(0,N);
    int Q;
    LL res=0;
    cin>>Q;
    while(Q--){
	int a,b;
	cin>>a>>b;
	int ca=lca(a,b,depth,parpar);
	LL ans=0;
	//cout<<"(a,b,ca)="<<a<<","<<b<<","<<ca<<endl;
	//cout<<"id(a,b,ca)="<<h.id[a]<<","<<h.id[b]<<","<<h.id[ca]<<endl;
	
	auto p=h.decomposition(ca,a);
	auto q=h.decomposition(ca,b);
	auto s=h.decomposition(ca,ca);
	for(auto &it:p)ans+=st.add(it.first,it.second,1ll);
	for(auto &it:q)ans+=st.add(it.first,it.second,1ll);
	ans-=st.get(s[0].first,s[0].second);
	st.add(s[0].first,s[0].second,-1ll);
	//	cout<<ans<<endl;
	res+=ans;
    }
    cout<<res<<endl;
}
0