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\n",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("\n");
261     return 0;
262 }
View Code

 

所以。。暴力出奇迹?

posted @ 2018-04-16 17:23  hk_lin  阅读(264)  评论(0编辑  收藏  举报