我为什么先做的GGS7?
询问最大子段和出在了树上,毫无疑问的树剖啊。
线段树的维护和GSS1一模一样。
最后树剖统计答案时从x到lca(x,y)之间的区间需要翻转(因写法而异)。
做过了[Ynoi2018]由乃的OJ,这种程度的水题虐着玩。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 inline int read(){ 7 int x=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 10 return x*f; 11 } 12 const int MAXN=100005; 13 const int INF=0x3f3f3f3f; 14 int a[MAXN],w[MAXN],head[MAXN],ecnt,fa[MAXN],siz[MAXN],dep[MAXN],pc[MAXN],top[MAXN],id[MAXN],tot; 15 int n,m,tag[MAXN*4],ql,qr,k,t[2]; 16 struct Node{ 17 int L,M,R,S; 18 }b[MAXN*4],q[2][MAXN]; 19 struct Edge{ 20 int to,nxt; 21 }e[MAXN*2]; 22 inline void add_edge(int bg,int ed){ 23 ecnt++; 24 e[ecnt].to=ed; 25 e[ecnt].nxt=head[bg]; 26 head[bg]=ecnt; 27 } 28 void dfs1(int x,int pre,int depth){ 29 fa[x]=pre; 30 dep[x]=depth; 31 siz[x]=1; 32 int maxsiz=-1; 33 for(int i=head[x];i;i=e[i].nxt){ 34 int ver=e[i].to; 35 if(ver==pre) continue; 36 dfs1(ver,x,depth+1); 37 siz[x]+=siz[ver]; 38 if(siz[ver]>maxsiz) maxsiz=siz[ver],pc[x]=ver; 39 } 40 } 41 void dfs2(int x,int topf){ 42 top[x]=topf; 43 id[x]=++tot; 44 w[tot]=a[x]; 45 if(!pc[x]) return; 46 dfs2(pc[x],topf); 47 for(int i=head[x];i;i=e[i].nxt){ 48 int ver=e[i].to; 49 if(ver==fa[x]||ver==pc[x]) continue; 50 dfs2(ver,ver); 51 } 52 } 53 #define mid ((l+r)>>1) 54 #define lc (o<<1) 55 #define rc ((o<<1)|1) 56 inline Node mer(Node x,Node y){ 57 Node ans; 58 ans.L=max(x.L,x.S+y.L); 59 ans.M=max(x.M,max(y.M,x.R+y.L)); 60 ans.R=max(y.R,y.S+x.R); 61 ans.S=x.S+y.S; 62 return ans; 63 } 64 inline Node revz(Node x){ 65 swap(x.L,x.R); 66 return x; 67 } 68 inline void pushup(int o){ 69 b[o]=mer(b[lc],b[rc]); 70 } 71 inline void pushdown(int o,int l,int r){ 72 if(tag[o]>1e9) return; 73 b[lc].S=tag[o]*(mid-l+1); 74 b[rc].S=tag[o]*(r-mid); 75 b[lc].L=b[lc].M=b[lc].R=(tag[o]>0?b[lc].S:0); 76 b[rc].L=b[rc].M=b[rc].R=(tag[o]>0?b[rc].S:0); 77 tag[lc]=tag[rc]=tag[o]; 78 tag[o]=INF; 79 } 80 void build(int o,int l,int r){ 81 if(l==r){ 82 b[o].S=w[l]; 83 b[o].L=b[o].M=b[o].R=(w[l]>0?w[l]:0); 84 return; 85 } 86 build(lc,l,mid); 87 build(rc,mid+1,r); 88 pushup(o); 89 } 90 void upd(int o,int l,int r){ 91 if(ql<=l&&r<=qr){ 92 b[o].S=k*(r-l+1); 93 b[o].L=b[o].M=b[o].R=(k>0?b[o].S:0); 94 tag[o]=k; 95 return; 96 } 97 pushdown(o,l,r); 98 if(mid>=ql) upd(lc,l,mid); 99 if(mid<qr) upd(rc,mid+1,r); 100 pushup(o); 101 } 102 Node query(int o,int l,int r){ 103 if(ql<=l&&r<=qr) return b[o]; 104 pushdown(o,l,r); 105 if(mid<ql) return query(rc,mid+1,r); 106 else if(mid>=qr) return query(lc,l,mid); 107 else return mer(query(lc,l,mid),query(rc,mid+1,r)); 108 } 109 inline void pathset(int x,int y){ 110 while(top[x]!=top[y]){ 111 if(dep[top[x]]<dep[top[y]]) swap(x,y); 112 ql=id[top[x]],qr=id[x]; 113 upd(1,1,n); 114 x=fa[top[x]]; 115 } 116 if(dep[x]>dep[y]) swap(x,y); 117 ql=id[x],qr=id[y]; 118 upd(1,1,n); 119 } 120 inline int getans(int x,int y){ 121 t[0]=t[1]=0;int ptr=0; 122 while(top[x]!=top[y]){ 123 if(dep[top[x]]<dep[top[y]]) swap(x,y),ptr^=1; 124 ql=id[top[x]],qr=id[x]; 125 q[ptr][++t[ptr]]=query(1,1,n); 126 x=fa[top[x]]; 127 } 128 ptr^=1;//这里需要特别注意一下 129 if(dep[x]>dep[y]) swap(x,y),ptr^=1; 130 ql=id[x],qr=id[y]; 131 q[ptr][++t[ptr]]=query(1,1,n); 132 Node ans; 133 ans.L=ans.M=ans.R=ans.S=0; 134 for(int i=1;i<=t[0];i++) 135 ans=mer(ans,revz(q[0][i]));//翻转 136 for(int i=t[1];i;i--) 137 ans=mer(ans,q[1][i]);//不翻转 138 return ans.M; 139 } 140 int main(){ 141 memset(tag,0x3f,sizeof tag); 142 n=read(); 143 for(int i=1;i<=n;i++) a[i]=read(); 144 for(int i=1;i<n;i++){ 145 int u=read(),v=read(); 146 add_edge(u,v); 147 add_edge(v,u); 148 } 149 dfs1(1,0,1); 150 dfs2(1,1); 151 build(1,1,n); 152 m=read(); 153 while(m--){ 154 int opt=read(); 155 if(opt==1){ 156 int x=read(),y=read(); 157 printf("%d\n",getans(x,y)); 158 } 159 if(opt==2){ 160 int x=read(),y=read();k=read(); 161 pathset(x,y); 162 } 163 } 164 return 0; 165 }