zoukankan      html  css  js  c++  java
  • 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
    ",ii,ans);
    221     }
    222 }
  • 相关阅读:
    javascript中createTextRange用法[转]
    在服务器端在线解压.ZIP文件的小工具(源码打包)以后向服务器发布程序就快了。
    关于extjs和coolite 收费以及版权的问题 请大家帮帮解释解释。
    关于目前千团大战与我的一些事情
    C#实现做秒杀器系列之一 网站登录
    CLR的执行模型 清晰明了
    socket 实现淘宝秒杀器(抢拍器) 附源码与截图
    MIME生成EXCEL 包括图片的写入 支持EXCEL2003 2007 草稿
    给WPF Browser Application创建数字证书(转)
    C#自动注册sqlite ado.net数据库驱动 及 自定义连接字符串
  • 原文地址:https://www.cnblogs.com/fzmh/p/4528415.html
Copyright © 2011-2022 走看看