Test instructions
A weighted undirected connected graph with a N-node M-Edge is given, which has a Q-order operation;
Each operation is to modify the weight of an edge, requiring each operation to output the minimum spanning tree weights and the graph;
n<=20000,m<=50000,q<=50000;
Exercises
The online solution is the division of the Ghost Livestock, each layer of the minimum spanning tree to narrow the problem to an acceptable range;
But that method is not good understanding and difficult to promote, so wyfcyx proposed a more enjoyable approach;
First of all, this problem cannot be maintained directly with LCT, because when an edge is deleted (the weight of the edge becomes larger), we cannot know whether there is a smaller edge between the two connected blocks.
In other words, LCT maintenance of the minimum spanning tree can not be deleted, so the use of partition to do a transformation;
We consider a time axis in which each edge is covered by the time period of its existence as an interval;
So for a time point of inquiry, the edges on this graph are those that are covered above the point;
So with the position of the line tree, the interval of each edge is split to no more than log, and then hangs on the node of the segment tree;
Now from the root to a segment of the tree leaves, all through the knot hanging edge one by one join LCT run the minimum spanning tree, run to the bottom is the answer to that point in time;
And because to query all, it should be in the deep search backtracking, delete the edge just inserted, and then return to the parent node, and then to another sub-node search;
But LCT can't support the deletion of the edge ah ... There is also no support for branching out to the left and right subtrees of each other to make a version ...
But Uncle Wyfcyx appeared! Because the operation of LCT is very simple, only link and cut, and just for the opposite operation;
Therefore records each time joins the side which bounces off and joins the edge, back when the direct inverse operation restores the LCT to be able, such complexity is still guaranteed;
Although this is guaranteed, but the actual operation of the very card! This algorithm is equivalent to each edge added two times deleted two times, and then counted on the LCT of the large constant, so not very good;
The card constant, Time complexity O (nlog^2n) can be in the BZ too;
The final answer is to open a long long;
Code:
#include <stdio.h> #include <string.h> #include <algorithm> #define N 71000#define M 51000#define MEM 800000#define LEN 1<<15#define Lson l,mid,no<<1#define Rson mid+1,r,no<<1|1#define which (x) (ch[fa[x ]][1]==x) using namespace Std;typedef long long ll;struct edge{int x,y,val,no;} E[m],list[mem];ll ans[m],tot;int last[m];int head[m<<2],next[mem],ce;int fa[N],ch[N][2],val[N],ma[N],n,m;int St[mem],stv[mem],top;bool opt[mem];bool rev[n],rt[n];inline Char getc () {static char *s,*t,buf[len]; if (s==t) {t= (s=buf) +fread (Buf,1,len,stdin); if (s==t) return EOF; } return *s++;} inline bool IsDigit (char x) {return ' 0 ' <=x&&x<= ' 9 ';} inline int read () {static char ch; static int D; while (!isdigit (Ch=getc ())); for (d=ch-' 0 '; IsDigit (Ch=getc ());) d=d*10+ch-' 0 '; return D;} inline void pushup (int x) {ma[x]=val[ma[ch[x][0]]]>val[ma[ch[x][1]]]?ma[ch[x][0]]:ma[ch[x][1]];ma[x]=val[ma[x]] >VAL[X]?MA[X]:x;} inline void pushdown (int x) {if (rev[x]) {swap (ch[x][0],ch[x][1]); rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]=0;}} inline void Down (int. x) {if (!rt[x]) down (fa[x]); Pushdown (x);} inline void Rotate (int x) {int f=fa[x];bool k=which (x); ch[f][k]=ch[x][!k];ch[x][!k]=f;if (rt[f]) rt[f]^=rt[x]^=1; Elsech[fa[f]][which (f)]=x;fa[ch[f][k]]=f;fa[x]=fa[f];fa[f]=x; Pushup (f);//pushup (x);} inline void splay (int x) {down (x), while (!rt[x]) {int f=fa[x];if (rt[f]) {Rotate (x); if (which (x) ^which (f)) Rotate (x); elserotate (f); Rotate (x);} Pushup (x);} inline void access (int x) {int y=0;while (x) {splay (x); rt[ch[x][1]]=1;ch[x][1]=y;rt[y]=0; Pushup (x); y=x,x=fa[x];}} inline void Mtr (int x) {access (x); Splay (x); swap (ch[x][0],ch[x][1]); rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;} inline bool Judge (int x,int y) {Mtr (x); Access (y); Splay (x); while (ch[x][1]) X=ch[x][1];return x==y;} inline void Cut (int x) {Mtr (x); static int t;t=e[x-n].x;access (t); Splay (x); rt[t]=1,fa[t]=0;ch[x][1]=0; Pushup (x); t=e[x-n].y;access (t); Splay (x); rt[t]=1,fa[t]=0;ch[x][1]=0; Pushup (x);} inline void Link (int x) {Mtr (x); fa[x]=e[x-n].x; MTR (x); fa[x]=e[x-n].y;} inline void Add (int no,edge &x) {list[++ce]=x;next[ce]=head[no];head[no]=ce;} inline void update (int l,int r,int no,int st,int En,edge &x) {if (st<=l&&r<=en) Add (no,x); Else{int mid=l +r>>1;if (en<=mid) Update (LSON,ST,EN,X), else if (st>mid) update (RSON,ST,EN,X), Elseupdate (lson,st,en,x), Update (RSON,ST,EN,X);}} inline void slove (int l,int r,int NO) {int cnt,i,temp;for (I=head[no],cnt=0;i;i=next[i]) {temp=0;if (!judge (list[i].x), LIST[I].Y) | | Val[temp=ma[list[i].x]]>=list[i].val) {if (temp) {cnt++,top++;st[top]=temp;stv[top]=val[temp];opt[top]=0; Cut (temp); tot-=val[temp];} Cnt++,top++;st[top]=list[i].no;opt[top]=1;val[list[i].no]=list[i].val; Link (list[i].no); tot+=list[i].val;}} if (l==r) {Ans[l]=tot;} Else{int Mid=l+r>>1;slove (Lson); Slove (Rson);} while (CNT) {if (opt[top]==0) {val[st[top]]=stv[top]; Link (St[top]); Tot+=val[st[top]];} Else{cut (St[top]); tot-=val[st[top];} top--;cnt--;}} int main () {int q,i,j,k,x,y,v; N=read (), M=read (), Q=read (); for (i=1;i<=m;i++) {e[i].x=read (), E[i].y=read (), E[i].val=read (); last[i]=1; E[i].no=i+n;} for (i=1;i<=q;i++) {x=read (), Y=read (); if (last[x]<=i-1) update (1,q,1,last[x],i-1,e[x]); last[x]=i,e[x].val=y;} for (i=1;i<=m;i++) {update (1,q,1,last[i],q,e[i]);} for (i=1;i<=n+m;i++) {rt[i]=1;ma[i]=i;} Slove (1,q,1); for (i=1;i<=q;i++) {printf ("%lld\n", Ans[i]);} return 0;}
BZOJ-2001 City Construction