UVALive 7148 LRIP【树分治+线段树】
题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过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 }