将删边改为插边,如果是无向图直接线段树合并即可,考虑如何将有向边转换为无向边
令$t_{i}$表示当插入到第$t_{i}$条边时恰好满足$x_{i}$与$y_{i}$在同一个强连通分量中,然后分类讨论:
1.$t_{i}<i$或$t_{i}$不存在,这条边无意义,删去;
2.$t_{i}ge i$,将所有这类边按照$t_{i}$排序,之后视作无向边进行操作即可
考虑如何求出$t_{i}$,整体二分,对于当前区间$[l,r]$,问题即如何求出时间在$[1,mid]$中所有边所构成的强连通分量
我们将$[1,mid]$中的边分为两类:1.答案(不等同于时间)小于$l$;2.答案在$[l,r]$中
第一类边对图的贡献仅仅只是强连通分量,即第一类边构成的图恰好是若干个强连通分量(否则就答案就不会小于$l$),因此用按秩合并并查集来维护强连通分量(要支持撤销)
第二类边的数量即当前询问区间,可以暴力加入再求tarjan(只能搜有新边的点,这样复杂度可以保证)
假设$n,m,q$同阶,总复杂度为$o(nlog_{2}n)$(并查集的$log_{n}$应该与整体二分和线段树合并独立)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define ll long long 5 #define mid (l+r>>1) 6 struct ji{ 7 int t,x,y; 8 }a[N<<1],e[N<<1],ee[N<<1]; 9 struct ji2{ 10 int nex,to; 11 }edge[N<<1]; 12 vector<int>vv,v[N<<1]; 13 vector<pair<int,int> >re; 14 map<int,int>mat[N]; 15 int V,E,n,m,q,p,x,y,head[N],vis[N],dfn[N],low[N],st[N],fa[N],sz[N],w[N],r[N],ls[N*100],rs[N*100],f[N*100]; 16 ll ans[N<<1],sum[N*100]; 17 bool cmp(ji x,ji y){ 18 return x.t<y.t; 19 } 20 int find(int k){ 21 if (k==fa[k])return k; 22 return find(fa[k]); 23 } 24 void add(int x,int y){ 25 edge[E].nex=head[x]; 26 edge[E].to=y; 27 head[x]=E++; 28 } 29 void merge1(int x,int y){ 30 x=find(x); 31 y=find(y); 32 if (x!=y){ 33 if (sz[x]>sz[y])swap(x,y); 34 fa[x]=y; 35 sz[y]+=sz[x]; 36 re.push_back(make_pair(x,y)); 37 } 38 } 39 void dfs(int k){ 40 vis[k]=1; 41 dfn[k]=low[k]=++dfn[0]; 42 st[++st[0]]=k; 43 for(int i=head[k];i!=-1;i=edge[i].nex) 44 if (!dfn[edge[i].to]){ 45 dfs(edge[i].to); 46 low[k]=min(low[k],low[edge[i].to]); 47 } 48 else 49 if (vis[edge[i].to])low[k]=min(low[k],dfn[edge[i].to]); 50 if (dfn[k]==low[k]){ 51 int las=st[st[0]--]; 52 vis[las]=0; 53 while (las!=k){ 54 vis[st[st[0]]]=0; 55 merge1(st[st[0]],las); 56 las=st[st[0]--]; 57 } 58 } 59 } 60 void dfs(int l,int r,int x,int y){ 61 if (x>y)return; 62 if (l==r){ 63 for(int i=x;i<=y;i++) 64 if ((l<q)||(find(e[i].x)==find(e[i].y)))v[q-l+1].push_back(mat[e[i].x][e[i].y]); 65 return; 66 } 67 vv.clear(); 68 for(int i=x;i<=y;i++){ 69 if (e[i].t>mid)continue; 70 int x=find(e[i].x),y=find(e[i].y); 71 vv.push_back(x); 72 if (x!=y){ 73 vv.push_back(y); 74 add(x,y); 75 } 76 } 77 int sre=re.size(); 78 for(int i=0;i<vv.size();i++) 79 if (!dfn[vv[i]])dfs(vv[i]); 80 E=dfn[0]=0; 81 for(int i=0;i<vv.size();i++){ 82 head[vv[i]]=-1; 83 dfn[vv[i]]=0; 84 } 85 vv.clear(); 86 for(int i=x;i<=y;i++) 87 if ((e[i].t<=mid)&&(find(e[i].x)==find(e[i].y)))vv.push_back(i); 88 for(int i=x,j=vv.size();i<x+vv.size();i++) 89 if ((e[i].t>mid)||(find(e[i].x)!=find(e[i].y)))swap(e[i],e[vv[--j]]); 90 int svv=vv.size(); 91 dfs(mid+1,r,x+svv,y); 92 while (re.size()>sre){ 93 sz[re[re.size()-1].second]-=sz[re[re.size()-1].first]; 94 fa[re[re.size()-1].first]=re[re.size()-1].first; 95 re.pop_back(); 96 } 97 dfs(l,mid,x,x+svv-1); 98 } 99 void update(int &k,int l,int r,int x,int y){ 100 if (!x)return; 101 if (!k)k=++V; 102 f[k]+=y; 103 sum[k]+=x*y; 104 if (l==r)return; 105 if (x<=mid)update(ls[k],l,mid,x,y); 106 else update(rs[k],mid+1,r,x,y); 107 } 108 long long query(int k,int l,int r,int x){ 109 if (l==r)return min(x,f[k])*l; 110 if (x<=f[rs[k]])return query(rs[k],mid+1,r,x); 111 return sum[rs[k]]+query(ls[k],l,mid,x-f[rs[k]]); 112 } 113 int merge(int k1,int k2){ 114 if ((!k1)||(!k2))return k1+k2; 115 if ((!ls[k1])&&(!rs[k1])){ 116 f[k1]+=f[k2]; 117 sum[k1]+=sum[k2]; 118 return k1; 119 } 120 ls[k1]=merge(ls[k1],ls[k2]); 121 rs[k1]=merge(rs[k1],rs[k2]); 122 f[k1]=f[ls[k1]]+f[rs[k1]]; 123 sum[k1]=sum[ls[k1]]+sum[rs[k1]]; 124 return k1; 125 } 126 void merge2(int x,int y){ 127 x=find(x); 128 y=find(y); 129 if (x!=y){ 130 if (sz[x]>sz[y])swap(x,y); 131 fa[x]=y; 132 sz[y]+=sz[x]; 133 r[y]=merge(r[x],r[y]); 134 } 135 } 136 int main(){ 137 scanf("%d%d%d",&n,&m,&q); 138 for(int i=1;i<=n;i++)scanf("%d",&w[i]); 139 memset(head,-1,sizeof(head)); 140 for(int i=1;i<=m;i++){ 141 scanf("%d%d",&e[i].x,&e[i].y); 142 e[i].t=1;//t表示插入的时间 143 mat[e[i].x][e[i].y]=i; 144 } 145 for(int i=1;i<=q;i++){ 146 scanf("%d%d%d",&p,&x,&y); 147 if (p==1)e[mat[x][y]].t=q-i+1; 148 if (p==2)w[x]+=y; 149 a[i]=ji{p,x,y}; 150 } 151 sort(e+1,e+m+1,cmp); 152 memcpy(ee,e,sizeof(ee)); 153 for(int i=1;i<=m;i++)mat[e[i].x][e[i].y]=i; 154 for(int i=1;i<=n;i++){ 155 fa[i]=i; 156 sz[i]=1; 157 } 158 dfs(1,q,1,m); 159 for(int i=1;i<=n;i++){ 160 fa[i]=i; 161 sz[i]=1; 162 update(r[i],0,1e9,w[i],1); 163 } 164 for(int i=m;i;i--){ 165 for(int j=0;j<v[i].size();j++)merge2(ee[v[i][j]].x,ee[v[i][j]].y); 166 if (a[i].t==3)ans[++ans[0]]=query(r[find(a[i].x)],0,1e9,a[i].y); 167 if (a[i].t==2){ 168 update(r[find(a[i].x)],0,1e9,w[a[i].x],-1); 169 w[a[i].x]-=a[i].y; 170 update(r[find(a[i].x)],0,1e9,w[a[i].x],1); 171 } 172 } 173 for(int i=ans[0];i;i--)printf("%lld ",ans[i]); 174 }