码迷,mamicode.com
首页 > 其他好文 > 详细

UVALive 7148 LRIP【树分治+线段树】

时间:2015-05-25 18:32:58      阅读:458      评论:0      收藏:0      [点我收藏+]

标签:

  题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过D。

  做法是树分治+线段树,假设树根是x,y是其当前需要处理的子树,对于子树y,需要处理出两个数组MN,MX,MN[i]表示以x为第一个数字的不下降子序列中第i个数的最小值,MX[i]表示以x为第一个数字的不上升子序列中第i个数的最大值。如果当前子树有一个以x为首的不下降序列,那么我们就需要在之前处理的子树中找一条以x为首的满足约束条件不上升序列,可以用线段树来查询。同时每做完一颗子树的时候,用MN,MX对线段树进行更新。对于不经过x的情况可以递归下去处理。

  代码:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #define N 1000010
  5 using namespace std;
  6 int dp,p[N],s[N],pre[N],tt[N],flag[N],father[N],tmproot,n,d,ttt;
  7 int i,v[N],a,b,mn,mx,MN[N],MX[N],U,V,ans;
  8 int l[N],r[N],smn[N],smx[N],vsmn[N],vsmx[N];
  9 void build(int x,int a,int b)
 10 {
 11     int m;
 12     l[x]=a;r[x]=b;
 13     if (x>ttt) ttt=x;
 14     if (b-a>1)
 15     {
 16         m=(a+b)>>1;
 17         build(2*x,a,m);
 18         build(2*x+1,m,b);
 19     }
 20 }
 21 void clean(int x)
 22 {
 23     if (vsmn[x])
 24     {
 25         smn[x]=0;
 26         if (2*x<=ttt)
 27         vsmn[2*x]=1;
 28         if (2*x+1<=ttt)
 29         vsmn[2*x+1]=1;
 30         vsmn[x]=0;
 31     }
 32     
 33     if (vsmx[x])
 34     {
 35         smx[x]=0;
 36         if (2*x<=ttt)
 37         vsmx[2*x]=1;
 38         if (2*x+1<=ttt)
 39         vsmx[2*x+1]=1;
 40         vsmx[x]=0;
 41     }
 42 }
 43 void change(int x,int a,int b,int c,int typ)
 44 {
 45     int m;
 46     clean(x);
 47     if ((a<=l[x])&&(r[x]<=b))
 48     {
 49         if (typ==0)
 50         smn[x]=max(smn[x],c);
 51         else
 52         smx[x]=max(smx[x],c);
 53         return;
 54     }
 55     m=(l[x]+r[x])>>1;
 56     if (a<m) change(2*x,a,b,c,typ);
 57     if (m<b) change(2*x+1,a,b,c,typ);
 58     clean(2*x);clean(2*x+1);
 59     if (!typ)
 60     smn[x]=max(smn[2*x],smn[2*x+1]);
 61     else
 62     smx[x]=max(smx[2*x],smx[2*x+1]);
 63 }
 64 int query(int x,int a,int b,int typ)
 65 {
 66     int m,ans=0;
 67     clean(x);
 68     if ((a<=l[x]&&(r[x]<=b)))
 69     {
 70         if (typ==0)
 71         return smn[x];
 72         else
 73         return smx[x];
 74     }
 75     m=(l[x]+r[x])>>1;
 76     if (a<m) ans=max(ans,query(2*x,a,b,typ));
 77     if (m<b) ans=max(ans,query(2*x+1,a,b,typ));
 78     return ans;
 79 } 
 80 void link(int x,int y)
 81 {
 82     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
 83 }
 84 int getroot(int x,int fa,int sum)
 85 {
 86     int i,f=0;
 87     i=p[x];
 88     father[x]=fa;
 89     s[x]=1;
 90     while (i)
 91     {
 92         if ((tt[i]!=fa)&&(!flag[tt[i]]))
 93         {
 94             getroot(tt[i],x,sum);
 95             s[x]=s[x]+s[tt[i]];
 96             if (s[tt[i]]>sum/2) f=1;
 97         }
 98         i=pre[i];
 99     }
100     if (sum-s[x]>sum/2) f=1;
101     if (!f) tmproot=x;
102 }
103 void dfs(int x,int fa,int mn,int mx)
104 {
105     int i;
106     i=p[x];
107     if (v[x]>=v[fa])
108     {
109         if (mn) 
110         {
111             mn++;
112             MN[mn]=min(MN[mn],v[x]);
113         }
114         if (v[x]>v[fa])
115         mx=0;
116     }
117     if (v[x]<=v[fa])
118     {
119         if (mx) 
120         {
121             mx++;
122             MX[mx]=max(MX[mx],v[x]);
123         }
124         if (v[x]<v[fa])
125         mn=0;
126     }
127     U=max(U,mn);
128     V=max(V,mx);
129     while (i)
130     {
131         if ((tt[i]!=fa)&&(!flag[tt[i]]))
132             dfs(tt[i],x,mn,mx);
133         i=pre[i];
134     }
135 }
136 void work(int x,int sum)
137 {
138     int i,j,k,root;
139     getroot(x,0,sum);
140     root=tmproot;
141     i=p[root];
142     flag[root]=1;
143     while (i)
144     {
145         if (flag[tt[i]]==0)
146         {
147             if (tt[i]==father[root])
148             work(tt[i],sum-s[root]);
149             else
150             work(tt[i],s[tt[i]]);
151         }
152         i=pre[i];
153     }
154 //------------------------------
155     i=p[root];
156     vsmn[1]=1;
157     vsmx[1]=1;
158     while (i)
159     {
160         if (!flag[tt[i]])
161         {
162             for (j=2;j<=U;j++)
163             MN[j]=0x37373737;
164             for (j=2;j<=V;j++)
165             MX[j]=0;
166             U=0;V=0;
167             dfs(tt[i],root,1,1);
168             for (j=2;j<=U;j++)
169             {    
170                 if (MN[j]-d<=v[root])
171                 ans=max(ans,j);
172                 k=MN[j]-d;
173                 if (k<1) k=1;
174                 if (k<=v[root])
175                 ans=max(ans,j+query(1,k-1,v[root],1)-1);
176             }
177             for (j=2;j<=V;j++)
178             {
179                 if (MX[j]+d>=v[root])
180                 ans=max(ans,j);
181                 k=MX[j]+d;
182                 if (k>100000) k=100000;
183                 if (k>=v[root])
184                 ans=max(ans,j+query(1,v[root]-1,k,0)-1);
185             }
186             
187             
188             for (j=2;j<=U;j++)
189             change(1,MN[j]-1,MN[j],j,0);
190             for (j=2;j<=V;j++)
191             change(1,MX[j]-1,MX[j],j,1);
192         }
193         i=pre[i];
194     }
195     flag[root]=0;
196 }
197 int main()
198 {
199     build(1,0,100000);
200     for (i=0;i<=100000;i++)
201     MN[i]=0x37373737;
202     int test,ii=0;
203     scanf("%d",&test);
204     while (test)
205     {
206     test--;
207     ii++;
208     dp=0;memset(p,0,sizeof(p));
209     scanf("%d%d",&n,&d);
210     for (i=1;i<=n;i++)
211     scanf("%d",&v[i]);
212     for (i=1;i<=n-1;i++)
213     {
214         scanf("%d%d",&a,&b);
215         link(a,b);
216         link(b,a);
217     }
218     ans=1;
219     work(1,n);
220     printf("Case #%d: %d\n",ii,ans);
221     }
222 }

 

UVALive 7148 LRIP【树分治+线段树】

标签:

原文地址:http://www.cnblogs.com/fzmh/p/4528415.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!