[luogu5163]WD与地图

将删边改为插边,如果是无向图直接线段树合并即可,考虑如何将有向边转换为无向边

令$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 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/13833615.html