P5618 [SDOI2015]道路修建 題解
阿新 • • 發佈:2021-07-21
沒想到線段樹
Description.
有一個 \(2\times n\) 的網格,有 \(3\times n-2\) 條邊。
需要支援邊權修改,以及求區間最小生成樹。
Solution.
就是考慮區間合併時,會多出來兩條邊,再找到最大的那條邊刪掉。
由於最小生成樹必定存在
線段樹強上。
分別維護
右邊兩條橫邊、選了幾條豎邊,最左邊和最右邊的豎邊邊權,左邊、右邊一圈的最小值,最小橫邊,答案
然後直接暴力維護即可。
Coding.
//是啊,你就是那隻鬼了,所以被你碰到以後,就輪到我變成鬼了{{{ #include<bits/stdc++.h> using namespace std;typedef long long ll; template<typename T>inline void read(T &x) { x=0;char c=getchar(),f=0; for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1; for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48); f?x=-x:x; }/*}}}*/ const int N=60005; int n,m,hg[N][2],rw[N]; struct node { int rhg0,rhg1,cnt,lsh,rsh,lvl,rvl,mx;ll res; //分別為右邊兩條橫邊、選了幾條豎邊,最左邊和最右邊的豎邊邊權 //左邊、右邊一圈的最小值,最小橫邊,答案 inline node operator+(node b) { node a=*this,r;r.rhg0=b.rhg0,r.rhg1=b.rhg1,r.rsh=b.rsh,r.lsh=a.lsh; int a1=a.rhg0,a2=a.rhg1,b1=a.rvl,b2=b.lvl,mx; mx=max(max(a1,a2),max(b1,b2)),r.mx=max(max(a1,a2),max(a.mx,b.mx)); r.res=a.res+b.res+a1+a2-mx,r.lvl=a.lvl,r.rvl=b.rvl,r.cnt=a.cnt+b.cnt; if(mx==b1) { if(a.rsh!=b1) return r;else if(a.cnt>1) return r.cnt--,r; return r.cnt--,r.lsh=b.lsh,r.lvl=max(max(b.lvl,a.mx),max(a1,a2)),r; } if(mx==b2) { if(b.lsh!=b2) return r;else if(b.cnt>1) return r.cnt--,r; return r.cnt--,r.rsh=a.rsh,r.rvl=max(max(a.rvl,b.mx),max(a1,a2)),r; } return r; } }T[N<<2]; inline node init(int x) {return(node){hg[x][0],hg[x][1],1,rw[x],rw[x],rw[x],rw[x],0,rw[x]};} inline void pt(node x) {printf("%d,%d %d %d,%d,%d,%d %d ! %lld\n",x.rhg0,x.rhg1,x.cnt,x.lsh,x.rsh,x.lvl,x.rvl,x.mx,x.res);} inline void build(int x,int l,int r) { if(l==r) return T[x]=init(l),void(); build(x<<1,l,(l+r)>>1),build(x<<1|1,((l+r)>>1)+1,r),T[x]=T[x<<1]+T[x<<1|1]; //pt(T[x<<1]),pt(T[x<<1|1]),pt(T[x]),putchar('\n'); } inline void updat(int x,int l,int r,int dw) { if(l==r) return T[x]=init(l),void(); if(dw<=((l+r)>>1)) updat(x<<1,l,(l+r)>>1,dw),T[x]=T[x<<1]+T[x<<1|1]; else updat(x<<1|1,((l+r)>>1)+1,r,dw),T[x]=T[x<<1]+T[x<<1|1]; } inline node query(int x,int l,int r,int dl,int dr) { int md;if(dl<=l&&r<=dr) return T[x];else md=(l+r)>>1; if(dl>md) return query(x<<1|1,md+1,r,dl,dr); else if(md>=dr) return query(x<<1,l,md,dl,dr); return query(x<<1,l,md,dl,dr)+query(x<<1|1,md+1,r,dl,dr); } int main() { read(n),read(m);for(int i=1;i<n;i++) read(hg[i][0]); for(int i=1;i<n;i++) read(hg[i][1]); for(int i=1;i<=n;i++) read(rw[i]); build(1,1,n);for(int x1,y1,x2,y2,vl;m--;) { char fg[5];scanf("%s",fg),read(x1); if(*fg=='Q') read(x2),printf("%lld\n",query(1,1,n,min(x1,x2),max(x1,x2)).res); else { read(y1),read(x2),read(y2),read(vl); if(y1==y2) rw[y1]=vl,updat(1,1,n,y1); else hg[min(y1,y2)][x1-1]=vl,updat(1,1,n,min(y1,y2)); } } return 0; }