結果
| 問題 | No.399 動的な領主 |
| コンテスト | |
| ユーザー |
btk
|
| 提出日時 | 2016-07-15 14:12:11 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 673 ms / 2,000 ms |
| コード長 | 4,627 bytes |
| コンパイル時間 | 2,159 ms |
| コンパイル使用メモリ | 185,068 KB |
| 実行使用メモリ | 43,364 KB |
| 最終ジャッジ日時 | 2024-11-07 18:32:28 |
| 合計ジャッジ時間 | 8,929 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 19 |
ソースコード
#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]=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;
}
btk