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

令$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. PostgreSQL 大小写问题 一键修改表名、字段名为小写

    标准的SQL是不区分大小写的.但是PostgreSQL对于数据库中对象的名字允许使用支持大小写区分的定义和引用方法.方式就是在DDL中用双引号把希望支持大小的对象名括起来.比如希望创建一个叫AAA的表 ...

  2. Nginx安装及核心配置解析

    安装 使用yum进行安装 yum install -y nginx 查看nginx的安装位置 whereis nginx 启动测试 nginx 核心配置文件结构 读取Nginx自带的Nginx配置文件 ...

  3. 5.27日Scrum Metting

    日期:2021年5月27日 会议主要内容概述:确定账单数据格式,确定需要添加新的图表,确定模板分享功能任务量. 一.进度情况# 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 ...

  4. LP-DDR 和其他 DDR

    一篇技術文檔比較 LP-DDR 和其他 DDR. 就觀念來說,LP-DDR 就是 Low Power 的 DDR:但就架構來說,LP-DDR 和其他 DDR 是截然不同的東西. 他們分屬不同的 JDE ...

  5. 常用JAVA API :HashSet 和 TreeSet

    set容器的特点是不包含重复元素,也就是说自动去重. HashSet HashSet基于哈希表实现,无序. add(E e)//如果容器中不包含此元素,则添加. clear()//清空 contain ...

  6. 21.6.17 test

    \(NOI\) 模拟赛. \(T1\) 正解树形DP,由于不是很熟悉概率和期望所以打了个20pts暴力,说不定见多了概率能打出60pts半正解?最后的虚树更不会. \(T2\) 又是概率,还有坐标数量 ...

  7. 字符串与模式匹配算法(一):BF算法

    一.BF算法的基本思想 BF(Brute Force)算法是模式匹配中最简单.最直观的算法.该算法最基本的思想是从主串的第 start 个字符起和模式P(要检索的子串)的第1个字符比较,如果相等,则逐 ...

  8. MyBatis源码分析(八):设计模式

    Mybatis中用到的设计模式 1. 建造者(Builder)模式: 表示一个类的构建与类的表示分离,使得同样的构建过程可以创建不同的表示.建造者模式是一步一步创建一个复杂的对象,他只允许用户只通过指 ...

  9. hdu 3863 No Gambling (不会证明,但是是对的,,)

    题意: N=4时 规则: 双方每次可以连接自己颜色的两个点(相邻,长度为1),线和线不能交叉重叠. 蓝方要连接左右,红方要连接上下. 蓝方先.问谁先连接? 思路: 经过观察....蓝方胜....... ...

  10. Android Studio 查看SQLite数据库存储位置及文件

    前言: 之前开发的一个记账本APP,用的是SQLite数据库,会有一些网友问如何查看数据库,这篇博文对此进行一个说明. 操作: 1.通过DDMS(Dalvik Debug Monitor Servic ...