|
| 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