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

令$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(n\log_{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\n",ans[i]);
174 }

[luogu5163]WD与地图的更多相关文章

  1. WD与地图 解题报告

    WD与地图 哎,我好傻啊,看了题解还弄错了一遍,靠着lbw指点才董 题意:给一个带点权有向图,要求支持删边,查询一个scc前\(k\)大权值,修改点权,不强制在线. 显然倒序处理变成加边 考虑求出每条 ...

  2. 【LUOGU???】WD与地图 整体二分 线段树合并

    题目大意 有一个简单有向图.每个点有点权. 有三种操作: 修改点权 删除一条边 询问和某个点在同一个强连通分量中的点的前 \(k\) 大点权和. \(n\leq 100000,m,q\leq 2000 ...

  3. 洛谷P5163 WD与地图

    只有洛谷的毒瘤才会在毒瘤月赛里出毒瘤题...... 题意:三个操作,删边,改变点权,求点x所在强连通分量内前k大点权之和. 解:狗屎毒瘤数据结构乱堆...... 整体二分套(tarjan+并查集) + ...

  4. P5163 WD与地图(整体二分+权值线段树)

    传送门 细节要人命.jpg 这题思路太新奇了--首先不难发现可以倒着做变成加边,但是它还需要我们资瓷加边的同时维护强连通分量.显然加边之后暴力跑是不行的 然后有一个想法,对于一条边\((u,v)\), ...

  5. P5163 WD与地图 [整体二分,强连通分量,线段树合并]

    首先不用说,倒着操作.整体二分来做强连通分量,然后线段树合并,这题就做完了. // powered by c++11 // by Isaunoya #include <bits/stdc++.h ...

  6. 题解 洛谷 P5163 【WD与地图】

    首先将操作倒序,把删边转化为加边.先考虑若边是无向边,条件为连通,要怎么处理. 可以用并查集来维护连通性,对每个连通块维护一颗权值线段树,连通块的合并用线段树合并来实现,线段树同时也支持了修改点权. ...

  7. 使用R画地图数据

    用R画地图数据 首先,从这里下载中国地图的GIS数据,这是一个压缩包,完全解压后包含三个文件(bou2_4p.dbf.bou2_4p.shp和bou2_4p.shx),将这三个文件解压到同一个目录下. ...

  8. iOS地图

    地图 1.主要用到了地图展示和定位功能 CoreLocation框架的使用: 导入头文件        #import <CoreLocation/CoreLocation.h>CoreL ...

  9. Android百度地图附加搜索和公交路线方案搜索

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入) Q  Q:408365330     E-Mail:egojit@qq.com 综述: 今 ...

随机推荐

  1. 手把手教你 Docker部署可视化工具Grafana

    一.Grafana的简单介绍 Grafana是开源的.炫酷的可视化监控.分析利器,无论您的数据在哪里,或者它所处的数据库是什么类型,您都可以将它与Grafana精美地结合在一起.它还有丰富的套件供您选 ...

  2. 5-基本的sql查询以及函数的使用

    基本SQL查询语句以及函数的使用 格式元素 描述 YYYY 四位的年份 MONTH 月份的英文全称 MON 月份的英文简写 MM 月份的数字表示 DD 日起的1-31数字表示 D 星期几的数字表示1- ...

  3. SphereEx 创始人张亮云咖访谈回顾:构建数据服务的新思路

    2021 年 7 月 21 日,2021 亚马逊云科技中国峰会在上海盛大开幕.本次大会以"构建新格局,共赢云时代"为主题,邀请到来自技术社区.开源软件基金会.开源创业代表.女性开发 ...

  4. 题解 CF736D Permutations

    link Description 现在,你有一个二分图,点数为 \(2n\). 已知这个二分图的完备匹配的个数是奇数. 现在你要知道,删除每条边后,完备匹配个数是奇数还是偶数. \(1\le n\le ...

  5. 题解「雅礼集训 2017 Day7」事情的相似度

    题目传送门 Description 给出一个长度为 \(n\) 的 \(01\) 串为 \(s\),设 \(t_i\) 为 \(s_{1,2,..,i}\),有 \(m\) 次查询,每次查询给出 \( ...

  6. 详解build-gradle文件

    目录 gradle 两个build.gradle文件 最外层目录下的build.gradle文件 jcenter dependencies闭包 app目录下的build.gradle文件 com.an ...

  7. Java 创建PDF打印小册子

    概述 PDF打印小册子是指将PDF格式文档在打印成刊物前需要提前进行的页面排版,以便在打印后装订成册.下面以Java代码展示如何来实现.这里调用Free Spire.PDF for Java中的Pdf ...

  8. Google Style Guides

    Google Style Guides Google Style Guides Google 开源项目风格指南 (zh-google-styleguide.readthedocs.io)

  9. Git: 搭建一个本地私人仓库

    Git: 搭建一个本地私人仓库 寝室放个电脑.实验室也有个电脑 为进行数据同步,充分利用实验室的服务器搭建了个本地私人仓库 1. 安装流程 当然首先保证服务器上与PC机上都已经安装了可用的Git 在P ...

  10. dwr简单应用及一个反向ajax消息推送

    由于项目中最近需要用到dwr实现一些功能,因此在网上和dwr官网上找了一些资料进行学习.在此记录一下.(此处实现简单的dwr应用和dwr消息反向推送) 一.引入dwr的包 <dependency ...