题目大意:给一颗树,树上每个节点都有一个权。两种操作,1 l r:询问l到r路径上所有点权组成的串的最大子串和;2 l r c:将l到r路径上的所有点权改为c。
思路:如果不是树,那么就基本和SPOJ 1043一样。但是题目是树,这里采用树链剖分。
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef long long LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100011122;
const double INFF=1e100;
const double eps=1e-8;
const LL mod=1000000007;
const int NN=100010;
const int MM=1000010;
/* ****************** */
struct TR
{
int l,r,sum,fg;
bool ok;
int l_r,r_l,maxll;
int mid()
{
return (l+r)>>1;
}
}tr[NN*4];
int a[NN],b[NN];
struct G
{
int v,next;
}E[NN*2];
int p[NN],T;
//c_dfs1
int deep[NN],si[NN],per[NN],anc[NN];
//c_dfs2
int tsp,pos[NN],top[NN];
void add(int u,int v)
{
E[T].v=v;
E[T].next=p[u];
p[u]=T++;
}
void c_dfs1(int u,int fa,int cen)
{
anc[u]=fa;
deep[u]=cen;
si[u]=1;
per[u]=-1;
int i,v;
for(i=p[u];i+1;i=E[i].next)
{
v=E[i].v;
if(v==fa)continue;
c_dfs1(v,u,cen+1);
si[u]+=si[v];
if(per[u]==-1 || si[v]>si[ per[u] ])
per[u]=v;
}
}
void c_dfs2(int u,int fa,int now_top)
{
pos[u]=++tsp;
top[u]=now_top;
if(per[u]!=-1)c_dfs2(per[u],u,now_top);
int i,v;
for(i=p[u];i+1;i=E[i].next)
{
v=E[i].v;
if(v==per[u] || v==fa)continue;
c_dfs2(v,u,v);
}
}
void up(TR &fa,TR &ls,TR &rs)
{
fa.sum=ls.sum+rs.sum;
fa.maxll=max(ls.maxll,rs.maxll);
fa.maxll=max(fa.maxll,ls.r_l+rs.l_r);
fa.l_r=max(ls.l_r,ls.sum+rs.l_r);
fa.r_l=max(rs.r_l,rs.sum+ls.r_l);
}
void push_up(int R)
{
up(tr[R],tr[R<<1],tr[R<<1|1]);
}
void down(int R,int col)
{
tr[R].fg=col;
tr[R].ok=true;
tr[R].sum=col*(tr[R].r-tr[R].l+1);
if(col>0)
{
tr[R].l_r=tr[R].r_l=tr[R].maxll=tr[R].sum;
}
else
{
tr[R].l_r=tr[R].r_l=tr[R].maxll=col;
}
}
void push_down(int R)
{
if(tr[R].ok)
{
down(R<<1,tr[R].fg);
down(R<<1|1,tr[R].fg);
tr[R].ok=false;
}
}
void build(int l,int r,int R)
{
tr[R].l=l;
tr[R].r=r;
tr[R].ok=false;
if(l==r)
{
tr[R].sum=tr[R].l_r=tr[R].r_l=tr[R].maxll=b[l];
return;
}
int mid=tr[R].mid();
build(l,mid,R<<1);
build(mid+1,r,R<<1|1);
push_up(R);
}
void update(int l,int r,int R,int col)
{
if(l<=tr[R].l && tr[R].r<=r)
{
down(R,col);
return;
}
push_down(R);
int mid=tr[R].mid();
if(l<=mid)
update(l,r,R<<1,col);
if(r>=mid+1)
update(l,r,R<<1|1,col);
push_up(R);
}
TR query(int l,int r,int R)
{
if(l<=tr[R].l && tr[R].r<=r)
return tr[R];
push_down(R);
int t=0,mid=tr[R].mid();
TR temp[3];
if(l<=mid)t++,temp[1]=query(l,r,R<<1);
if(r>=mid+1)t+=2,temp[2]=query(l,r,R<<1|1);
if(t<3)return temp[t];
up(temp[0],temp[1],temp[2]);
return temp[0];
}
void c_update(int u,int v,int col)
{
while(top[u]!=top[v])
{
if(deep[ top[u] ] > deep[ top[v] ])
swap(u,v);
update(pos[ top[v] ],pos[v],1,col);
v=anc[ top[v] ];
}
if(pos[u]>pos[v])
swap(u,v);
update(pos[u],pos[v],1,col);
}
int c_query(int u,int v)
{
int zz,yy,ans=0;
TR tt;
zz=yy=0;
while(top[u]!=top[v])
{
if(deep[ top[u] ] > deep[ top[v] ])
{
// printf("check==[%d,%d]\n",pos[ top[u] ],pos[u]);
tt=query(pos[ top[u] ],pos[u],1);
// printf("check ok\n");
ans=max(ans,tt.maxll);
ans=max(ans,zz+tt.r_l);
zz=max(zz+tt.sum,tt.l_r);
u=anc[ top[u] ];
}
else
{
// printf("check==[%d,%d]\n",pos[ top[v] ],pos[v]);
tt=query(pos[ top[v] ],pos[v],1);
// printf("check ok\n");
ans=max(ans,tt.maxll);
ans=max(ans,yy+tt.r_l);
yy=max(yy+tt.sum,tt.l_r);
v=anc[ top[v] ];
}
}
if(pos[u]>pos[v])
{
swap(u,v);
swap(zz,yy);
}
tt=query(pos[u],pos[v],1);
ans=max(ans,tt.maxll);
ans=max(ans,zz+tt.sum+yy);
ans=max(ans,zz+tt.l_r);
ans=max(ans,tt.r_l+yy);
return ans;
}
void solve(int n,int m)
{
int op,l,r,c;
build(1,n,1);
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&l,&r);
c=c_query(l,r);
// cout<<"ans==";
printf("%d\n",c);
}
else
{
scanf("%d%d%d",&l,&r,&c);
c_update(l,r,c);
}
}
}
int main()
{
int n,m,i;
int u,v;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(p,-1,sizeof(p));
T=0;
for(i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
c_dfs1(1,-1,0);
tsp=0;
c_dfs2(1,-1,1);
for(i=1;i<=n;i++)
{
b[ pos[i] ]=a[i];
}
scanf("%d",&m);
solve(n,m);
}
return 0;
}