P1620小白逛公园加强版
背景
Crash觉得小白逛公园有点简单了,稍微加强了一下……
描述
小新经常陪小白去公园玩,也就是所谓的遛狗啦……在小新家附近有n个公园,这些公园通过一些路径相连,并保证每两个公园之间有且仅有一条通路相连(也就是说这是一棵树),小白早就看花了眼,自己也不清楚该去哪些公园玩了。
小白对每个公园都有一个评价(可正可负),并且它只会让小新做两件事:
1. 询问公园a到公园b路径上最大连续公园的评价和,就是说我们把公园a到公园b路径上的公园(包括a和b)排成一条直线,那么小白希望知道一段连续的公园的评价和最大为多少。
2. 修改公园a到公园b路径上(包括a和b)每个公园的评价值。
小新现在已经处理不了n超过10的情况,因此请你来帮忙……
格式
输入格式
第一行有一个自然数,表示n
第二行有n个自然数,表示一开始小白对每个公园的评价(评价值的绝对值不超过10000)
下面有n-1行,每行两个数a和b,表示公园a和公园b直接由道路相连
再下面一行有一个自然数,表示m
最后m行,每行第一个数k表示要执行的操作。如果k为1,那么后面有两个自然数a和b,表示询问公园a到公园b路径上(包含a和b)最大的连续公园评价和(如果这条路径上每个公园的评价都为负数,那么最大连续和为0)。如果k为2,那么后面有三个自然数a、b和c,表示把公园a到公园b路径上所有的公园(包括a和b)的评价都修改为c。(c的绝对值不超过10000)
输出格式
对于每次询问,输出最大连续和。(用空格隔开,最后要有换行符)
限制
小数据1s,大数据2s
(时间是足够的……)
提示
对于30%的数据:n,m <= 100
对于70%的数据:n,m <= 50000
对于100%的数据:n,m <= 100000
int solvemax(int x,int y){ tree res1,res2;//一个是lca左边的,一个是lca右边的 while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y),swap(res1,res2);//交换x,y时也要交换res1,res2 res1=merge(query(1,p[top[x]],p[x]),res1);//合并区间 x=fa[top[x]]; } if(dep[x]<dep[y])swap(x,y),swap(res1,res2); res1=merge(query(1,p[y],p[x]),res1); swap(res1.lmax,res1.rmax); res1=merge(res1,res2); return res1.mx; }
大概就是这一段代码需要注意的地方比较多。。。写完之后就会发现自己对树链剖分有了更加深入的了解(似乎是一句废话。。。。
这道题还需要注意的是lazytag的标记问题。。。一般都是直接赋值为0。。。不过这道题有可能会修改为0。。。所以这里要注意值不能为0。。。
大概还要记住要return!!!!
然后是代码。。。。zyf神犇告诉我这是一道码农题。。。不过代码还不到200行(大雾。。。。。不过p党似乎有写300+。。真是太神辣!!!
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define mod 1000000007 13 #define inf 1000000010 14 #define maxn 100005 15 #define maxm 100005*2 16 #define eps 1e-10 17 #define ll long long 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 23 using namespace std; 24 int read(){ 25 int x=0,f=1;char ch=getchar(); 26 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 27 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 28 return x*f; 29 } 30 struct tree{ 31 int l,r,sum,mx,lmax,rmax,lazy; 32 tree(){lmax=rmax=mx=sum=0;lazy=-inf;l=r=0;} 33 }f[maxn*4]; 34 struct edge{ 35 int go,next; 36 }e[maxm]; 37 int head[maxn],w[maxn],top[maxn],fa[maxn],p[maxn],son[maxn],s[maxn],dep[maxn],a[maxn],tot,cnt; 38 39 void pushup(int i){ 40 f[i].sum=(f[(i<<1)+1].sum+f[i<<1].sum); 41 f[i].lmax=max(0,max(f[i<<1].lmax,f[i<<1].sum+f[(i<<1)+1].lmax)); 42 f[i].rmax=max(0,max(f[(i<<1)+1].rmax,f[(i<<1)+1].sum+f[i<<1].rmax)); 43 f[i].mx=max(0,max(f[i<<1].mx,max(f[(i<<1)+1].mx,f[i<<1].rmax+f[(i<<1)+1].lmax))); 44 } 45 46 void update(int i,int x){ 47 f[i].sum=(f[i].r-f[i].l+1)*x; 48 f[i].lmax=f[i].rmax=f[i].mx=max(0,f[i].sum); 49 f[i].lazy=x; 50 return; 51 } 52 53 void pushdown(int i){ 54 if(f[i].lazy==-inf)return; 55 else{ 56 update(i<<1,f[i].lazy); 57 update((i<<1)+1,f[i].lazy); 58 f[i].lazy=-inf; 59 } 60 } 61 void build(int i,int left,int right){ 62 int mid=(left+right)/2; 63 f[i].l=left;f[i].r=right;f[i].lmax=f[i].mx=f[i].rmax=0;f[i].lazy=-inf; 64 if(left==right){ 65 f[i].sum=a[left]; 66 f[i].lmax=f[i].rmax=f[i].mx=max(0,a[left]); 67 return; 68 } 69 build(i<<1,left,mid); 70 build((i<<1)+1,mid+1,right); 71 pushup(i); 72 } 73 74 void change(int i,int left,int right,int v){ 75 int mid=(f[i].l+f[i].r)/2; 76 if(f[i].l==left&&f[i].r==right){ 77 update(i,v); 78 return; 79 } 80 pushdown(i); 81 if(mid>=right)change(i<<1,left,right,v); 82 else if(mid<left)change((i<<1)+1,left,right,v); 83 else change(i<<1,left,mid,v),change((i<<1)+1,mid+1,right,v); 84 pushup(i); 85 } 86 87 tree merge(tree res1,tree res2){ 88 tree res; 89 res.sum=res1.sum+res2.sum; 90 res.lmax=max(0,max(res1.lmax,res1.sum+res2.lmax)); 91 res.rmax=max(0,max(res2.rmax,res2.sum+res1.rmax)); 92 res.mx=max(0,max(res1.rmax+res2.lmax,max(res1.mx,res2.mx))); 93 return res; 94 } 95 96 tree query(int i,int left,int right){ 97 int mid=(f[i].l+f[i].r)>>1; 98 if(f[i].l==left&&f[i].r==right)return f[i]; 99 pushdown(i); 100 if(mid>=right)return query(i<<1,left,right); 101 else if(mid<left)return query((i<<1)+1,left,right); 102 else return merge(query(i<<1,left,mid),query((i<<1)+1,mid+1,right)); 103 } 104 105 void insert(int u,int v){ 106 e[++tot].go=v;e[tot].next=head[u];head[u]=tot; 107 } 108 void ins(int u,int v){ 109 insert(u,v);insert(v,u); 110 } 111 void dfs(int x){ 112 s[x]=1; 113 for(int y=son[x]=0,i=head[x];i;i=e[i].next){ 114 if(dep[y=e[i].go]==0){ 115 dep[y]=dep[x]+1;fa[y]=x;dfs(y); 116 s[x]+=s[y];if(s[y]>s[son[x]])son[x]=y; 117 } 118 } 119 } 120 void dfs2(int x,int chain){ 121 p[x]=++cnt;top[x]=chain;a[p[x]]=w[x]; 122 if(son[x])dfs2(son[x],chain); 123 for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 124 if(y!=fa[x]&&y!=son[x])dfs2(y,y); 125 } 126 void solvechange(int x,int y,int v){ 127 while(top[x]!=top[y]){ 128 if(dep[top[x]]<dep[top[y]])swap(x,y); 129 change(1,p[top[x]],p[x],v); 130 x=fa[top[x]]; 131 } 132 if(dep[x]>dep[y])swap(x,y); 133 change(1,p[x],p[y],v); 134 } 135 int solvemax(int x,int y){ 136 tree res1,res2; 137 while(top[x]!=top[y]){ 138 if(dep[top[x]]<dep[top[y]])swap(x,y),swap(res1,res2); 139 res1=merge(query(1,p[top[x]],p[x]),res1); 140 x=fa[top[x]]; 141 } 142 if(dep[x]<dep[y])swap(x,y),swap(res1,res2); 143 res1=merge(query(1,p[y],p[x]),res1); 144 swap(res1.lmax,res1.rmax); 145 res1=merge(res1,res2); 146 return res1.mx; 147 } 148 int main(){ 149 //freopen("input.txt","r",stdin); 150 //freopen("output.txt","w",stdout); 151 int n=read();dep[1]=1; 152 for1(i,n)w[i]=read(); 153 for1(i,n-1){ 154 int u=read(),v=read(); 155 ins(u,v); 156 } 157 dfs(1);dfs2(1,1); 158 build(1,1,n); 159 n=read(); 160 for1(i,n){ 161 int x=read(); 162 if(x==1){ 163 int y=read(),z=read(); 164 printf("%d ",solvemax(y,z)); 165 } 166 else{ 167 int y=read(),z=read();x=read(); 168 solvechange(y,z,x); 169 } 170 } 171 printf("\n"); 172 return 0; 173 }