[SP6779]GSS7 - Can you answer these queries VII:树链剖分,线段树

我为什么先做的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 }

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9277252.html