# BZOJ4860 BJOI2017 树的难题 点分治、线段树合并

  1 #include<bits/stdc++.h>
2 #define INF 0x7fffffff
3 #define int long long
4 #define mid ((l + r) >> 1)
5 //This code is written by Itst
6 using namespace std;
7
9     int a = 0;
10     bool f = 0;
11     char c = getchar();
12     while(c != EOF && !isdigit(c)){
13         if(c == '-')
14             f = 1;
15         c = getchar();
16     }
17     while(c != EOF && isdigit(c)){
18         a = (a << 3) + (a << 1) + (c ^ '0');
19         c = getchar();
20     }
21     return f ? -a : a;
22 }
23
24 const int MAXN = 200010;
25 vector < pair < int , int > > Edge[MAXN];
26 struct node{
27     int l , r , maxN;
28 }Tree[MAXN * 30];
29 int N , M , L , R , ans , cntNode , nowSize , minSize , minInd , roota , rootb;
30 int val[MAXN] , size[MAXN] , sz[MAXN] , mx[MAXN];
31 bool vis[MAXN];
32
33 inline int allocate(){
34     int t = ++cntNode;
35     Tree[t].l = Tree[t].r = 0;
36     Tree[t].maxN = -INF;
37     return t;
38 }
39
40 inline void pushup(int x){
41     Tree[x].maxN = max(Tree[Tree[x].l].maxN , Tree[Tree[x].r].maxN);
42 }
43
44 inline int max(int a , int b){
45     return a > b ? a : b;
46 }
47
48 int merge(int p , int q){
49     if(!p)
50         return q;
51     if(!q)
52         return p;
53     Tree[p].maxN = max(Tree[p].maxN , Tree[q].maxN);
54     Tree[p].l = merge(Tree[p].l , Tree[q].l);
55     Tree[p].r = merge(Tree[p].r , Tree[q].r);
56     return p;
57 }
58
59 void insert(int& now , int l , int r , int tar , int num){
60     if(!now)
61         now = allocate();
62     if(l == r)
63         Tree[now].maxN = max(Tree[now].maxN , num);
64     else{
65         if(mid >= tar)
66             insert(Tree[now].l , l , mid , tar , num);
67         else
68             insert(Tree[now].r , mid + 1 , r , tar , num);
69         pushup(now);
70     }
71 }
72
73 int query(int now , int l , int r , int L , int R){
74     if(l >= L && r <= R)
75         return Tree[now].maxN;
76     if(!now)
77         return -INF;
78     int maxN = -INF;
79     if(mid >= L)
80         maxN = max(maxN , query(Tree[now].l , l , mid , L , R));
81     if(mid < R)
82         maxN = max(maxN , query(Tree[now].r , mid + 1 , r , L , R));
83     return maxN;
84 }
85
86 void getSize(int x){
87     vis[x] = 1;
88     ++nowSize;
89     for(int i = 0 ; i < sz[x] ; ++i){
90         int t = Edge[x][i].second;
91         if(!vis[t])
92             getSize(t);
93     }
94     vis[x] = 0;
95 }
96
97 void getRoot(int x){
98     size[x] = vis[x] = 1;
99     int maxN = 0;
100     for(int i = 0 ; i < sz[x] ; ++i){
101         int t = Edge[x][i].second;
102         if(!vis[t]){
103             getRoot(t);
104             size[x] += size[t];
105             maxN = max(maxN , size[t]);
106         }
107     }
108     maxN = max(maxN , nowSize - size[x]);
109     if(maxN < minSize){
110         minSize = maxN;
111         minInd = x;
112     }
113     vis[x] = 0;
114 }
115
116 void dfs(int x , int c , int len , int nowCol){
117     if(len > R)
118         return;
119     vis[x] = 1;
120     mx[len] = max(mx[len] , c);
121     for(int i = 0 ; i < sz[x] ; ++i){
122         int t = Edge[x][i].second;
123         if(!vis[t])
124             dfs(Edge[x][i].second , nowCol == Edge[x][i].first ? c : c + val[Edge[x][i].first] , len + 1 , Edge[x][i].first);
125     }
126     vis[x] = 0;
127 }
128
129 void solve(int x){
130     nowSize = cntNode = roota = rootb = 0;
131     minSize = INF;
132     getSize(x);
133     getRoot(x);
134     int root = minInd;
135     getSize(root);
136     vis[root] = 1;
137     for(int i = 0 ; i < sz[root] ; ++i){
138         int t = Edge[root][i].second , r = Edge[root][i].first;
139         if(!vis[t]){
140             memset(mx , -0x3f , sizeof(int) * (size[t] + 1));
141             if(rootb && r != Edge[root][i - 1].first){
142                 roota = merge(roota , rootb);
143                 rootb = 0;
144             }
145             dfs(t , val[r] , 1 , r);
146             for(int i = 1 ; i <= size[t] && i < R && mx[i] != mx[0] ; ++i)
147                 ans = max(max(ans , i >= L && i <= R ? mx[i] : -INF) , max(query(roota , 1 , R , max(1 , L - i) , R - i) , query(rootb , 1 , R , max(1 , L - i) , R - i) - val[r]) + mx[i]);
148             ans = max(ans , mx[R]);
149             for(int i = 1 ; i <= size[t] && i < R && mx[i] != mx[0] ; ++i)
150                 insert(rootb , 1 , R , i , mx[i]);
151         }
152     }
153     for(int i = 0 ; i < sz[root] ; ++i){
154         int t = Edge[root][i].second;
155         if(!vis[t])
156             solve(t);
157     }
158 }
159
160 signed main(){
161 #ifndef ONLINE_JUDGE
162     freopen("3714.in" , "r" , stdin);
163     //freopen("3714.out" , "w" , stdout);
164 #endif
165     Tree[0].maxN = ans = -INF;
170     for(int i = 1 ; i <= M ; ++i)
172     for(int i = 1 ; i < N ; ++i){
184 }