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
",cs++,ret);
101     }
102     return 0;
103 }
View Code
原文地址:https://www.cnblogs.com/crackpotisback/p/4908004.html