• xcoj 1103 插线板(树链刨分求最大子段和)


    1103: 插线板

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 14  解决: 7

    题目描述

            从前有一堆古老的插线板,任意两个插线板之间只有一根导线相连,最终形成一个树状结构。我们假设电线的电阻可以忽略。由于年代久远,插线板的状况不容乐观。每个插线板都对电流有一定的影响,用一个整数表示,若为正,表示对电流起到稳定作用,越大越稳定,若为负,代表对电流产生不好的影响。插线板在连接后。这种影响会叠加,比如a和b连接,a的影响为-1,b为3,则a到b的影响为2。现在提供操作1和2,操作1表示求出插线板a到插线板b之间对电流影响最为乐观的一段的影响数值。(注:数据有问题,这一段元素可以为空)即将a到b的这条“链”取出,形成一个关于影响的序列,这个序列的最大子段和。操作2表示将a到b的链上所有插线板对电流的影响改为一个数值(包括a和b)。现给出插线板的初始状况,请按照要求进行操作,输出结果。

    输入

     单组测试数据

    第一行为插线板个数n。

    第二行为插线板1到n初始状态对电流的影响数值。(数值绝对值不超过10000)

    第三行开始有n-1行,每行两个数a和b,表示a、b有电线连接,保证形成一棵树。

    之后一行有一个正整数m,代表操作个数。

    最后m行,每行第一个数为1或2,代表操作种类,若为1,后面跟随两个数l和r,代表求出l和r之间的最好影响数值。若为2,后面跟随三个数l、r和c,代表修改l到r的插线板的影响为c。

    输出

    对每个操作1输出一个整数,代表最好影响数值,每个输出用一个空格隔开。

    样例输入

    5 -3 -2 1 2 3 1 2 2 3 1 4 4 5 3 1 2 5 2 3 4 2 1 2 5

    样例输出

    5 9

    提示

     n,m<=100000

    来源

    图论专题


    emm这题卡了我好久。。。

    由于我校oj的数据贼弱。。暴力就可以过,甚至比我写的o(log(n)^2*n)还快。

    暴力的做法就是对于题目所说的点求最近公共祖先(Tarjan+并查集,欧拉序列+st,求2^k的祖先然后不断向上找公共祖先),然后修改的时候把所有点逐个修改,求值的时候把所有点拿出来,求前缀和,维护最小值搞一下就好了。

    学长的博客链接做法:http://www.cnblogs.com/neopenx/p/4503066.html ,暴力法。

      1 #include "cstdio"
      2 #include "cstring"
      3 #include "vector"
      4 #include "algorithm"
      5 using namespace std;
      6 #define maxn 100005
      7 #define inf 0x3f3f3f3f
      8 int head[maxn],qhead[maxn],lag[maxn],kth[maxn],tot1,tot2,f[maxn],vis[maxn],ancestor[maxn],p[maxn],s1[maxn],s2[maxn];
      9 bool isUpdate[maxn];
     10 struct Edge
     11 {
     12     int to,next;
     13 }e[maxn*2];
     14 struct Query
     15 {
     16     int from,to,next,idx,c;
     17 }q[maxn*2];
     18 void addedge(int u,int v)
     19 {
     20     e[tot1].to=v;
     21     e[tot1].next=head[u];
     22     head[u]=tot1++;
     23 }
     24 void addquery(int u,int v,int idx,int c=inf)
     25 {
     26     q[tot2].from=u;
     27     q[tot2].to=v;
     28     q[tot2].next=qhead[u];
     29     q[tot2].idx=idx;
     30     if(c!=inf) q[tot2].c=c;
     31     qhead[u]=tot2++;
     32 }
     33 int find(int x) {return x!=f[x]?f[x]=find(f[x]):x;}
     34 void Union(int u,int v)
     35 {
     36     u=find(u),v=find(v);
     37     if(u!=v) f[v]=u;
     38 }
     39 void LCA(int u)
     40 {
     41     vis[u]=true;
     42     f[u]=u;
     43     for(int i=head[u];i!=-1;i=e[i].next)
     44     {
     45         int v=e[i].to;
     46         if(!vis[v])
     47         {
     48             p[v]=u;
     49             LCA(v);
     50             Union(u,v);
     51         }
     52     }
     53     for(int i=qhead[u];i!=-1;i=q[i].next)
     54     {
     55         int v=q[i].to;
     56         if(vis[v]) ancestor[q[i].idx]=find(v);
     57         //or storage e[i].lca=e[i^1].lca=find(v)
     58     }
     59 }
     60 int sum(int num)
     61 {
     62     s2[0]=s1[0];
     63     int Max=0,Min=0;
     64     for(int i=1; i<num; i++)
     65         s2[i]=s2[i-1]+s1[i];
     66     for(int i=0;i<num;i++)
     67     {
     68         Min=min(Min,s2[i]);
     69         Max=max(Max,s2[i]-Min);
     70     }
     71     return Max;
     72 }
     73 int main()
     74 {
     75     //freopen("in.txt","r",stdin);
     76     int T,n,m,u,v,c,cmd,qcnt=0;
     77     scanf("%d",&n);
     78     tot1=tot2=0;
     79     memset(head,-1,sizeof(head));
     80     memset(qhead,-1,sizeof(qhead));
     81     memset(vis,0,sizeof(vis));
     82     memset(isUpdate,0,sizeof(isUpdate));
     83     for(int i=1;i<=n;i++) scanf("%d",&lag[i]);
     84     for(int i=0; i<n-1; i++)
     85     {
     86         scanf("%d%d",&u,&v);
     87         addedge(u,v);
     88         addedge(v,u);
     89     }
     90     scanf("%d",&m);
     91     for(int i=0; i<m; i++)
     92     {
     93         scanf("%d",&cmd);
     94         if(cmd==2)
     95         {
     96             scanf("%d%d%d",&u,&v,&c);
     97             addquery(u,v,i,c);
     98             addquery(v,u,i,c);
     99             isUpdate[i]=true;
    100         }
    101         else
    102         {
    103             scanf("%d%d",&u,&v);
    104             addquery(u,v,i);
    105             addquery(v,u,i);
    106         }
    107     }
    108     LCA(1);
    109     vector<int> ans;
    110     for(int i=0; i<tot2; i=i+2)
    111     {
    112         int u=q[i].from,v=q[i].to,idx=q[i].idx;
    113         int ed=ancestor[idx],cnt=0;
    114         if(isUpdate[qcnt])
    115         {
    116             int c=q[i].c;
    117             while(u!=ed) lag[u]=c,u=p[u];
    118             lag[ed]=c;
    119             while(v!=ed) lag[v]=c,v=p[v];
    120         }
    121         else
    122         {
    123             while(u!=ed) s1[cnt++]=lag[u],u=p[u];
    124             s1[cnt++]=lag[ed];
    125             vector<int> rev;
    126             while(v!=ed) rev.push_back(lag[v]),v=p[v];
    127             for(int j=rev.size()-1; j>=0; j--) s1[cnt++]=rev[j];
    128             int x=sum(cnt);
    129             ans.push_back(x);
    130         }
    131         qcnt++;
    132     }
    133     for(int i=0;i<ans.size()-1;i++) printf("%d ",ans[i]);
    134     printf("%d
    ",ans[ans.size()-1]);
    135 }
    View Code

    然后我的做法是经典的线段树求区间最大子段和的做法,维护包含区间左端点的最大值lt,右端点的最大值rt,区间内最大值in,以及区间总和all。但是题目给的是一棵树,我们把它树链刨分以后再把一段一段地求前述四个值并合并。然后找到合并后的最大值即为答案。

      1 #include<bits/stdc++.h>
      2 #define clr(x) memset(x,0,sizeof(x))
      3 #define clr_1(x) memset(x,-1,sizeof(x))
      4 #define INF 0x3f3f3f3f
      5 #define mod 1000000007
      6 #define LL long long
      7 using namespace std;
      8 const int N=1e4+10;
      9 struct edg
     10 {
     11     int next,to;
     12 }edge[N<<1];
     13 int head[N],etot;
     14 void addedge(int u,int v)
     15 {
     16     edge[++etot]=(edg){head[u],v};
     17     head[u]=etot;
     18     return ;
     19 }
     20 int fro[N],bac[N],dep[N],fa[N],val[N],top[N],clk,tsize[N],son[N],dfn[N];
     21 struct node
     22 {
     23     int l,r,tag,lt,rt,in,all;
     24 }tree[N<<2];
     25 int n,m,k,u,v,c,op;
     26 void init()
     27 {
     28     etot=0;
     29     clk=0;
     30     clr_1(head);
     31     dep[1]=0;
     32     fa[1]=1;
     33     return ;
     34 }
     35 void dfs1(int u)
     36 {
     37     top[u]=u;
     38     tsize[u]=1;
     39     son[u]=0;
     40     int p;
     41     for(int i=head[u];i!=-1;i=edge[i].next)
     42     {
     43         p=edge[i].to;
     44         if(p!=fa[u])
     45         {
     46             fa[p]=u;
     47             dep[p]=dep[u]+1;
     48             dfs1(p);
     49             tsize[u]+=tsize[p];
     50             if(!son[u] || tsize[p]>tsize[son[u]] )
     51                 son[u]=p;
     52         }
     53     }
     54     return ;
     55 }
     56 void dfs2(int u)
     57 {
     58     fro[u]=++clk;
     59     dfn[clk]=u;
     60     int p;
     61     if(son[u])
     62     {
     63         top[son[u]]=top[u];
     64         dfs2(son[u]);
     65     }
     66     for(int i=head[u];i!=-1;i=edge[i].next)
     67     {
     68         p=edge[i].to;
     69         if(p!=fa[u] && p!=son[u])
     70             dfs2(p);
     71     }
     72     bac[u]=clk;
     73     return ;
     74 }
     75 void pushup(int i)
     76 {
     77     tree[i].all=tree[i<<1].all+tree[i<<1|1].all;
     78     tree[i].lt=max(max(tree[i<<1].lt,tree[i<<1].all+tree[i<<1|1].lt),tree[i].all);
     79     tree[i].rt=max(max(tree[i<<1|1].rt,tree[i<<1|1].all+tree[i<<1].rt),tree[i].all);
     80     tree[i].in=max(max(tree[i<<1].in,tree[i<<1|1].in),tree[i<<1].rt+tree[i<<1|1].lt);
     81     return ;
     82 }
     83 void pushdown(int i)
     84 {
     85     if(tree[i].tag!=INF)
     86     {
     87         if(tree[i].l!=tree[i].r)
     88         {
     89             tree[i<<1].tag=tree[i].tag;
     90             tree[i<<1].all=(tree[i<<1].r-tree[i<<1].l+1)*tree[i<<1].tag;
     91             tree[i<<1].lt=tree[i<<1].rt=tree[i<<1].in=(tree[i<<1].tag>=0?tree[i<<1].all:tree[i<<1].tag);
     92             tree[i<<1|1].tag=tree[i].tag;
     93             tree[i<<1|1].all=(tree[i<<1|1].r-tree[i<<1|1].l+1)*tree[i<<1|1].tag;
     94             tree[i<<1|1].lt=tree[i<<1|1].rt=tree[i<<1|1].in=(tree[i<<1|1].tag>=0?tree[i<<1|1].all:tree[i<<1|1].tag);
     95         }
     96         tree[i].tag=INF;
     97     }
     98     return ;
     99 }
    100 void init(int i,int l,int r)
    101 {
    102     tree[i]=(node){l,r,INF};
    103     if(l==r)
    104     {
    105         tree[i].lt=tree[i].rt=tree[i].in=tree[i].all=val[dfn[l]];
    106         return ;
    107     }
    108     int mid=(l+r)>>1;
    109     init(i<<1,l,mid);
    110     init(i<<1|1,mid+1,r);
    111     pushup(i);
    112     return ;
    113 }
    114 void update(int i,int l,int r,int c)
    115 {
    116     if(tree[i].l>=l && tree[i].r<=r)
    117     {
    118         tree[i].all=(tree[i].r-tree[i].l+1)*c;
    119         tree[i].lt=tree[i].rt=tree[i].in=(c>=0?tree[i].all:c);
    120         tree[i].tag=c;
    121         return ;
    122     }
    123     pushdown(i);
    124     int mid=(tree[i].l+tree[i].r)>>1;
    125     if(l<=mid)
    126         update(i<<1,l,r,c);
    127     if(r>mid)
    128         update(i<<1|1,l,r,c);
    129     pushup(i);
    130     return ;
    131 }
    132 node query(int i,int l,int r)
    133 {
    134     if(tree[i].l>=l && tree[i].r<=r)
    135         return tree[i];
    136     pushdown(i);
    137     int mid=(tree[i].l+tree[i].r)>>1;
    138     if(l>mid)
    139         return query(i<<1|1,l,r);
    140     else if(r<=mid)
    141         return query(i<<1,l,r);
    142     else
    143     {
    144         node tmplt=query(i<<1,l,r),tmprt=query(i<<1|1,l,r);
    145         node tmp;
    146         tmp.all=tmplt.all+tmprt.all;
    147         tmp.lt=max(max(tmplt.lt,tmplt.all+tmprt.lt),tmp.all);
    148         tmp.rt=max(max(tmprt.rt,tmprt.all+tmplt.rt),tmp.all);
    149         tmp.in=max(max(tmplt.in,tmprt.in),tmplt.rt+tmprt.lt);
    150         return tmp;
    151     }
    152 }
    153 void tupdate(int u,int v,int c)
    154 {
    155     int tpu=top[u],tpv=top[v];
    156     while(tpu!=tpv)
    157     {
    158         if(dep[tpu]<dep[tpv])
    159         {
    160             swap(u,v);
    161             swap(tpu,tpv);
    162         }
    163         update(1,fro[tpu],fro[u],c);
    164         u=fa[tpu];
    165         tpu=top[u];
    166     }
    167     if(dep[u]<dep[v])
    168         swap(u,v);
    169     update(1,fro[v],fro[u],c);
    170     return ;
    171 }
    172 int tquery(int u,int v)
    173 {
    174     int tpu=top[u],tpv=top[v];
    175     node tmp[2];
    176     clr(tmp);
    177     bool flag[2]={0,0};
    178     int now=0;
    179     node tmpn,tp;
    180     int ans=0;
    181     while(tpu!=tpv)
    182     {
    183         if(dep[tpu]<dep[tpv])
    184         {
    185             swap(u,v);
    186             swap(tpu,tpv);
    187             now^=1;
    188         }
    189         tmpn=query(1,fro[tpu],fro[u]);
    190         if(!flag[now])
    191         {
    192             tmp[now]=tmpn;
    193             flag[now]=1;
    194         }
    195         else
    196         {
    197             tp.all=tmp[now].all+tmpn.all;
    198             tp.lt=max(max(tmpn.lt,tmpn.all+tmp[now].lt),tp.all);
    199             tp.rt=max(max(tmp[now].rt,tmp[now].all+tmpn.rt),tp.all);
    200             tp.in=max(max(tmp[now].in,tmpn.in),tmpn.rt+tmp[now].lt);
    201             tmp[now]=tp;
    202         }
    203         u=fa[tpu];
    204         tpu=top[u];
    205     }
    206     if(dep[u]<dep[v])
    207         swap(u,v),now^=1;
    208     tmpn=query(1,fro[v],fro[u]);
    209     if(flag[now])
    210      {
    211         tp.all=tmp[now].all+tmpn.all;
    212         tp.lt=max(max(tmpn.lt,tmpn.all+tmp[now].lt),tp.all);
    213         tp.rt=max(max(tmp[now].rt,tmp[now].all+tmpn.rt),tp.all);
    214         tp.in=max(max(tmp[now].in,tmpn.in),tmpn.rt+tmp[now].lt);
    215         tmpn=tp;
    216      }
    217     if(flag[now^1])
    218     {
    219         tp.in=max(max(tmp[now^1].in,tmpn.in),tmpn.lt+tmp[now^1].lt);
    220         tmpn=tp;
    221     }
    222     return tmpn.in;
    223 }
    224 int main()
    225 {
    226     init();
    227     scanf("%d",&n);
    228     for(int i=1;i<=n;i++)
    229         scanf("%d",&val[i]);
    230      for(int i=2;i<=n;i++)
    231      {
    232          scanf("%d%d",&u,&v);
    233          addedge(u,v);
    234          addedge(v,u);
    235      }
    236      dfs1(1);
    237      dfs2(1);
    238      init(1,1,n);
    239      scanf("%d",&m);
    240      bool inf=0;
    241      for(int i=1;i<=m;i++)
    242      {
    243          scanf("%d",&op);
    244          if(op==1)
    245          {
    246             scanf("%d%d",&u,&v);
    247             if(!inf)
    248             {
    249                 inf=1;
    250                 printf("%d",max(tquery(u,v),0));
    251             }
    252             else  printf(" %d",max(tquery(u,v),0));
    253          }
    254          else
    255          {
    256              scanf("%d%d%d",&u,&v,&c);
    257              tupdate(u,v,c);
    258          }
    259      }
    260     printf("
    ");
    261     return 0;
    262 }
    View Code

    所以。。暴力出奇迹?

  • 相关阅读:
    40个极简WordPress主题
    一些上流的CSS3图片样式
    15个最好的 HTML5 视频播放器
    优秀的IOS界面
    25 个超棒的 WordPress 主题(2012)
    Codekit 为Web前端打造的全能型神器(附推荐各种工具)
    10 个精彩的、激发灵感的 HTML5 游戏
    20个非常绚丽的 CSS3 特性应用演示
    25+ 个免费精美的商业风格的 WordPress 主题
    10 款非常棒的CSS代码格式化工具推荐
  • 原文地址:https://www.cnblogs.com/wujiechao/p/8857126.html
Copyright © 2020-2023  润新知