UVALive 7148 LRIP
LRIP
Time Limit: 10000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu
解题:树分治
参考了Oyking大神的解法
我们用map<int,int>维护上升序列,first表示value,second表示长度,按first由小到大,second由大到小排列,因为在val相同的时候,当然是越长越好,但是,Oyking大神说过的冗余上升序列,意思就是在你的值比他小,长度也比它小,那么在拼接那个下降的序列的时候,就会导致极差大,所以可以删除这些没用的。
我们在搜索下降序列的时候,可以对map进行lower_bound,找出极差范围内最大的长度,进行合并即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 100010; 4 struct arc{ 5 int to,next; 6 arc(int x = 0,int y = -1){ 7 to = x; 8 next = y; 9 } 10 }e[maxn<<1]; 11 bool vis[maxn]; 12 int head[maxn],val[maxn],D,ret,tot; 13 int sz[maxn],maxson[maxn]; 14 map<int,int>up; 15 void add(int u,int v){ 16 e[tot] = arc(v,head[u]); 17 head[u] = tot++; 18 } 19 void dfs(int u,int fa){ 20 sz[u] = 1; 21 maxson[u] = 0; 22 for(int i = head[u]; ~i; i = e[i].next){ 23 if(e[i].to == fa || vis[e[i].to]) continue; 24 dfs(e[i].to,u); 25 sz[u] += sz[e[i].to]; 26 maxson[u] = max(maxson[u],sz[e[i].to]); 27 } 28 } 29 int FindRoot(int sum,int u,int fa){ 30 int ret = u; 31 maxson[u] = max(maxson[u],sum - sz[u]); 32 for(int i = head[u]; ~i; i = e[i].next){ 33 if(e[i].to == fa || vis[e[i].to]) continue; 34 int x = FindRoot(sum,e[i].to,u); 35 if(maxson[x] < maxson[ret]) ret = x; 36 } 37 return ret; 38 } 39 void dfs_down(int u,int fa,int len){ 40 auto it = up.lower_bound(val[u] - D); 41 if(it != up.end()) ret = max(ret,it->second + 1 + len); 42 for(int i = head[u]; ~i; i = e[i].next){ 43 if(e[i].to == fa || vis[e[i].to] || val[e[i].to] < val[u]) continue; 44 dfs_down(e[i].to,u,len + 1); 45 } 46 } 47 void insert(int val,int len){ 48 auto x = up.lower_bound(val); 49 if(x != up.end() && x->second >= len) return; 50 auto ed = up.upper_bound(val); 51 auto it = map<int,int>::reverse_iterator(ed); 52 while(it != up.rend() && it->second <= len) ++it; 53 up.erase(it.base(),ed); 54 up[val] = len; 55 } 56 void dfs_up(int u,int fa,int len){ 57 insert(val[u],len); 58 for(int i = head[u]; ~i; i = e[i].next){ 59 if(e[i].to == fa || vis[e[i].to] || val[e[i].to] > val[u]) continue; 60 dfs_up(e[i].to,u,len + 1); 61 } 62 } 63 void work(int u,vector<int>&son){ 64 up.clear(); 65 up[val[u]] = 0; 66 for(int v:son){ 67 if(val[v] >= val[u]) dfs_down(v,0,1); 68 if(val[v] <= val[u]) dfs_up(v,0,1); 69 } 70 } 71 void solve(int u){ 72 dfs(u,0); 73 int root = FindRoot(sz[u],u,0); 74 vis[root] = true; 75 vector<int>son; 76 for(int i = head[root]; ~i; i = e[i].next) 77 if(!vis[e[i].to]) son.push_back(e[i].to); 78 work(root,son); 79 reverse(son.begin(),son.end()); 80 work(root,son); 81 for(int i = head[root]; ~i; i = e[i].next) 82 if(!vis[e[i].to]) solve(e[i].to); 83 } 84 int main(){ 85 int kase,n,u,v,cs = 1; 86 scanf("%d",&kase); 87 while(kase--){ 88 scanf("%d %d",&n,&D); 89 memset(head,-1,sizeof head); 90 memset(vis,false,sizeof vis); 91 tot = 0; 92 for(int i = 1; i <= n; ++i) 93 scanf("%d",val + i); 94 for(int i = ret = 1; i < n; ++i){ 95 scanf("%d%d",&u,&v); 96 add(u,v); 97 add(v,u); 98 } 99 solve(1); 100 printf("Case #%d: %d\n",cs++,ret); 101 } 102 return 0; 103 }
夜空中最亮的星,照亮我前行