Skip to content

Commit bf57793

Browse files
committed
Add fireworks' solutions of Seokhwan Choi
1 parent 746eb19 commit bf57793

File tree

2 files changed

+220
-0
lines changed

2 files changed

+220
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Author: Seokhwan Choi
3+
* Time Complexity: O((N+M) (log (N+M))^2 )
4+
*/
5+
6+
#include<stdio.h>
7+
#include<queue>
8+
#define MAXN 300100
9+
int n,m;
10+
int p[MAXN];
11+
int c[MAXN];
12+
struct ndata{//contains data for subtree (y=f(x), where y is minimum cost when distance to all leaf node is x
13+
long long int a,b;//y=ax+b at large x
14+
std::priority_queue<long long int> *pq;//saves slope changing points, slope change by 1 at each element
15+
ndata operator+(ndata r){//merge two data by adding them
16+
ndata s;//result(merged data)
17+
s.a=a+r.a;
18+
s.b=b+r.b;
19+
if(pq->size()>r.pq->size()){//merge smaller priority queue to larger priority queue
20+
s.pq=pq;
21+
while(r.pq->size()!=0){
22+
s.pq->push(r.pq->top());
23+
r.pq->pop();
24+
}
25+
}
26+
else{
27+
s.pq=r.pq;
28+
while(pq->size()!=0){
29+
s.pq->push(pq->top());
30+
pq->pop();
31+
}
32+
}
33+
return s;
34+
}
35+
};
36+
ndata d[MAXN];
37+
int main(){
38+
int i;
39+
scanf("%d%d",&n,&m);
40+
for(i=2;i<=n+m;i++){
41+
scanf("%d%d",&p[i],&c[i]);
42+
}
43+
for(i=n+m;i>0;i--){//initiallize
44+
d[i].a=0;
45+
d[i].b=0;
46+
d[i].pq=new std::priority_queue<long long>;
47+
}
48+
for(i=n+m;i>n;i--){//leaf nodes
49+
d[i].a=1;
50+
d[i].b=-c[i];
51+
d[i].pq->push(c[i]);//slope is -1 if x<c[i], 1 if x>c[i]
52+
d[i].pq->push(c[i]);//slope changes by 2
53+
d[p[i]]=d[p[i]]+d[i];//add the data to parent node
54+
}
55+
for(i=n;i>1;i--){
56+
//add edge to parent node
57+
while(d[i].a>1){//slope over 1 is useless because we can increase only one edge(edge toward parent node)
58+
d[i].a--;//slope decrease by 1
59+
d[i].b+=d[i].pq->top();//y=ax+b=(a-1)x+(b+x) at slope changing point
60+
d[i].pq->pop();
61+
}
62+
long long int ta=d[i].pq->top();//increase length of slope -1 part by c[i]
63+
d[i].pq->pop();
64+
long long int tb=d[i].pq->top();
65+
d[i].pq->pop();
66+
d[i].pq->push(tb+c[i]);//move location of slope 0, 1 part by c[i]
67+
d[i].pq->push(ta+c[i]);
68+
d[i].b-=c[i];//y is decreased by c[i] at sufficiently large x (slope 1 part)
69+
d[p[i]]=d[p[i]]+d[i];//add the data to parent node
70+
}
71+
while(d[1].a>0){//root node, y at slope 0 is the answer because it is minimum y
72+
d[1].a--;
73+
d[1].b+=d[1].pq->top();
74+
d[1].pq->pop();
75+
}
76+
printf("%lld\n",d[1].b);
77+
return 0;
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Author: Seokhwan Choi
3+
* Time Complexity: O(N+M log (N+M))
4+
* It is recommended to understand O((N+M) (log (N+M))^2) code before view this code
5+
*/
6+
7+
#include<stdio.h>
8+
#include<vector>
9+
#define MAXN 300100
10+
#define MAXLOGN 19
11+
int n,m;
12+
int p[MAXN];
13+
int c[MAXN];
14+
std::vector<int> el[MAXN];//list of child nodes
15+
int chk[MAXN];//DFS visit check
16+
int tv;//number of visited nodes in DFS
17+
int tm[MAXN];//DFS traverse order, tm[i] is i-th visited node
18+
int itm[MAXN];//node i is visited itm[i]-th in DFS
19+
int tend[MAXN];//subtree of i-th node is tm[i]~tend[i]
20+
int leaf[MAXN];//1 if leaf node(explosive), 0 otherwise, after renumbering nodes
21+
int np[MAXN];//parent node after renumbering nodes
22+
int nc[MAXN];//cost after renumbering nodes
23+
int nend[MAXN];//subtree of i-th node is i~nend[i] after renumbering
24+
long long int pnt[MAXN][2];//slope changing points, pnt[i][0]>=pnt[i][1]
25+
int pntn[MAXN];//number of slope changing points, doesn't exceed 2
26+
int it[1<<(MAXLOGN+1)];//segment tree, finds i which pnt[i][0] is maximum - so we can find maximum slope changing point
27+
long long int a[MAXN];//y=ax+b if x is larger than all slope changing points
28+
long long int b[MAXN];
29+
void dfs(int loc){//depth-first search for renumbering nodes
30+
tv++;
31+
chk[loc]=1;
32+
tm[tv]=loc;
33+
itm[loc]=tv;
34+
int i;
35+
for(i=0;i<el[loc].size();i++){
36+
dfs(el[loc][i]);
37+
}
38+
tend[loc]=tv;
39+
}
40+
void push(int loc,long long int val){//add slope changing point
41+
pnt[loc][pntn[loc]]=val;//we add val in increasing order
42+
pntn[loc]++;
43+
it[loc+(1<<MAXLOGN)]=loc;
44+
loc+=1<<MAXLOGN;
45+
loc/=2;
46+
while(loc>0){
47+
if(pnt[it[loc*2]][0]>pnt[it[loc*2+1]][0]){
48+
it[loc]=it[loc*2];
49+
}
50+
else{
51+
it[loc]=it[loc*2+1];
52+
}
53+
loc/=2;
54+
}
55+
}
56+
long long int pop(int start,int end){//pop maximum slope changing point in range[start,end]
57+
start+=1<<MAXLOGN;
58+
end+=1<<MAXLOGN;
59+
long long int res=0;//pnt[res][0] should be maximum
60+
//initially res=0, so pnt[res][0]=0, which is smaller than all other pnt[i][0]
61+
while(start<=end){
62+
if(start%2==1){
63+
if(pnt[it[start]][0]>pnt[res][0]){
64+
res=it[start];
65+
}
66+
start++;
67+
}
68+
if(end%2==0){
69+
if(pnt[it[end]][0]>pnt[res][0]){
70+
res=it[end];
71+
}
72+
end--;
73+
}
74+
start/=2;
75+
end/=2;
76+
}
77+
long long int ret=pnt[res][0];//return value
78+
long long int loc=res;//should erase pnt[loc][0]
79+
pntn[loc]--;
80+
if(pntn[loc]==0){
81+
pnt[loc][0]=0;
82+
}
83+
else{//pntn[loc] becomes 2 to 1
84+
pnt[loc][0]=pnt[loc][1];
85+
}
86+
loc+=1<<MAXLOGN;
87+
loc/=2;
88+
while(loc>0){
89+
if(pnt[it[loc*2]][0]>pnt[it[loc*2+1]][0]){
90+
it[loc]=it[loc*2];
91+
}
92+
else{
93+
it[loc]=it[loc*2+1];
94+
}
95+
loc/=2;
96+
}
97+
return ret;
98+
}
99+
int main(){
100+
int i;
101+
long long int ta,tb;
102+
scanf("%d%d",&n,&m);
103+
for(i=2;i<=n+m;i++){
104+
scanf("%d%d",&p[i],&c[i]);
105+
el[p[i]].push_back(i);
106+
}
107+
dfs(1);//DFS from root node(node 1) to renumber nodes
108+
for(i=1;i<=n+m;i++){
109+
np[i]=itm[p[tm[i]]];
110+
nc[i]=c[tm[i]];
111+
if(tm[i]>n)leaf[i]=1;
112+
nend[i]=tend[tm[i]];
113+
}//renumbering finished
114+
for(i=n+m;i>1;i--){
115+
if(leaf[i]==1){//if i is leaf node
116+
a[i]=1;
117+
b[i]=-nc[i];
118+
push(i,nc[i]);
119+
push(i,nc[i]);
120+
}
121+
else{//we can see slope-changing points of subtree of node i
122+
//add edge toward parent node to data
123+
while(a[i]>1){
124+
b[i]+=pop(i,nend[i]);
125+
a[i]--;
126+
}
127+
ta=pop(i,nend[i]);
128+
tb=pop(i,nend[i]);
129+
push(i,ta+nc[i]);
130+
push(i,tb+nc[i]);
131+
b[i]-=nc[i];
132+
}
133+
a[np[i]]+=a[i];//we should only merge a,b to parent node
134+
b[np[i]]+=b[i];//because we can see all slope-changing points of subtree
135+
}
136+
while(a[1]>0){
137+
b[1]+=pop(1,nend[1]);
138+
a[1]--;
139+
}
140+
printf("%lld\n",b[1]);
141+
return 0;
142+
}

0 commit comments

Comments
 (0)