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输出一个整数,代表最好影响数值,每个输出用一个空格隔开。
样例输入
样例输出
提示
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 }
然后我的做法是经典的线段树求区间最大子段和的做法,维护包含区间左端点的最大值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 }
所以。。暴力出奇迹?