正题

题目链接:https://www.luogu.com.cn/problem/P5163


题目大意

给出nnn个点mmm条有向边,点有权值,要求支持操作

  1. 删除一条边
  2. 修改一个点的权值
  3. 求一个点所在强连通分量中前kkk大权值和

1≤n≤105,1≤m,q≤2×1051\leq n\leq 10^5,1\leq m,q\leq 2\times 10^51≤n≤105,1≤m,q≤2×105


解题思路

首先删边肯定是时光倒流改成加边,然后考虑怎么继续做。

我们需要处理一些点集什么时候合并,这样的合并其实不会超过n−1n-1n−1次。

而且每次肯定是合并某条边(x,y)(x,y)(x,y)两个点所在的强连通分量,但是每次加入的一条边(x,y)(x,y)(x,y)不一定会即使生效。
我们可以考虑对于每条边求出它在后来加入哪条边加入之后生效了,这个可以考虑整体二分,我们每次把所有询问的边集在[0,mid][0,mid][0,mid]区间的边加入然后跑tarjantarjantarjan,把跑出来的强连通分量缩成一个点然后继续丢到右边跑,跑完右边的子区间之后再撤销这次tarjantarjantarjan缩起来的点然后跑左边。

这样一定是对的因为如果一条答案不在这个区间的边生效,那么它要不就在之前被合并了要么在这个区间内都合并不了,所以没有作用。

这个要用一个可撤销并查集,记得安秩合并就好了。

之后我们就有一个操作变成合并两个集合了,线段树合并做剩下的部分就行了

时间复杂度O(nlog⁡2n)O(n\log^2 n)O(nlog2n)(反正差不多同级就不写这么详细了


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<stack>
#define ll long long
#define mp(x,y) make_pair(x,y)
using namespace std;
const ll N=8e5+10;
struct node{ll to,next;
}a[N];
struct enode{ll x,y,t,T;
}e[N],p1[N],p2[N];
struct qnode{ll x,k;
}q[N];
struct snode{ll x,y,fa,dep;
}st[N];
ll n,m,t,tot,snt,clt,cnt,s[N];
ll ls[N],fa[N],dep[N],cl[N];
ll dfn[N],low[N],rt[N],ans[N];
bool ins[N];stack<ll> S;
map<pair<ll,ll> ,ll> emp;
void addl(ll x,ll y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return;
}
ll find(ll x)
{return (fa[x]==x)?x:find(fa[x]);}
ll Find(ll x)
{return (fa[x]==x)?x:(fa[x]=Find(fa[x]));}
void unionn(ll x,ll y){x=find(x);y=find(y);if(x==y)return;if(dep[x]>dep[y])swap(x,y);st[++snt]=(snode){x,y,fa[x],dep[y]};fa[x]=y;dep[y]=max(dep[y],dep[x]+1);
}
void clearto(ll z){while(snt>z){dep[st[snt].y]=st[snt].dep;fa[st[snt].x]=st[snt].fa;snt--;}return;
}
void tarjan(ll x){dfn[x]=low[x]=++cnt;S.push(x);ins[x]=1;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}else if(ins[y])low[x]=min(low[x],dfn[y]);}if(low[x]==dfn[x]){while(S.top()!=x){unionn(S.top(),x);ins[S.top()]=0;S.pop();}ins[x]=0;S.pop();}return;
}
void solve(ll l,ll r,ll L,ll R){if(L>R)return;if(l==r){for(ll i=L;i<=R;i++)e[i].T=l;return;}ll mid=(l+r)>>1,zt=snt;for(ll i=L;i<=R;i++)if(e[i].t<=mid){ll x=find(e[i].x),y=find(e[i].y);addl(x,y);cl[++clt]=x;cl[++clt]=y;}cnt=tot=0;for(ll i=1;i<=clt;i++)if(!dfn[cl[i]])tarjan(cl[i]);ll t1=0,t2=0;for(ll i=L;i<=R;i++){ll x=find(e[i].x),y=find(e[i].y);if(x==y)p1[++t1]=e[i];else p2[++t2]=e[i];}for(ll i=1;i<=t1;i++)e[L+i-1]=p1[i];for(ll i=1;i<=t2;i++)e[L+t1+i-1]=p2[i];while(clt)ls[cl[clt]]=dfn[cl[clt]]=low[cl[clt]]=0,clt--;solve(mid+1,r,L+t1,R);clearto(zt);solve(l,mid,L,L+t1-1);return;
}
bool cmp(enode x,enode y)
{return x.t<y.t;}
struct SegTree{ll cnt,w[N<<5],s[N<<5],ls[N<<5],rs[N<<5];void Change(ll &x,ll L,ll R,ll pos,ll val){if(!x)x=++cnt;w[x]+=val;s[x]+=pos*val;if(L==R)return;ll mid=(L+R)>>1;if(pos<=mid)Change(ls[x],L,mid,pos,val);else Change(rs[x],mid+1,R,pos,val);return;}ll Ask(ll x,ll L,ll R,ll k){if(k>=w[x])return s[x];if(L==R)return L*k;ll mid=(L+R)>>1;if(w[rs[x]]>=k)return Ask(rs[x],mid+1,R,k);return s[rs[x]]+Ask(ls[x],L,mid,k-w[rs[x]]);}ll Merge(ll x,ll y){if(!x||!y)return x+y;w[x]=w[x]+w[y];s[x]=s[x]+s[y];ls[x]=Merge(ls[x],ls[y]);rs[x]=Merge(rs[x],rs[y]);return x;}
//  ll Merge(ll x,ll y,ll L,ll R){//      if(!x||!y)return x+y;
//      w[x]=w[x]+w[y];
//      if(L==R)return x;
//      ll mid=(L+R)>>1;
//      ls[x]=Merge(ls[x],ls[y],L,mid);
//      rs[x]=Merge(rs[x],rs[y],mid+1,R);
//      return x;
//  }
}T;
void Merge(ll x,ll y){x=Find(x),y=Find(y);if(x==y)return;rt[x]=T.Merge(rt[x],rt[y]);fa[y]=x;return;
}
signed main()
{scanf("%lld%lld%lld",&n,&m,&t);for(ll i=1;i<=n;i++)scanf("%lld",&s[i]),fa[i]=i;for(ll i=1;i<=m;i++){scanf("%lld%lld",&e[i].x,&e[i].y);emp[mp(e[i].x,e[i].y)]=i;}for(ll i=t;i>=1;i--){ll op,x,y;scanf("%lld%lld%lld",&op,&x,&y);if(op==1)e[emp[mp(x,y)]].t=i;else if(op==2)q[i].x=-x,q[i].k=y,s[x]+=y;else if(op==3)q[i].x=x,q[i].k=y;}sort(e+1,e+1+m,cmp);solve(0,t+1,1,m);ll z=1;for(ll i=1;i<=n;i++)fa[i]=i,T.Change(rt[i],1,1e9,s[i],1);for(ll i=1;i<=t;i++){while(z<=m&&e[z].T<=i)Merge(e[z].x,e[z].y),z++;if(q[i].x<0){ll x=-q[i].x,w=q[i].k,f=Find(x);T.Change(rt[f],1,1e9,s[x],-1);s[x]-=w;T.Change(rt[f],1,1e9,s[x],1);}else if(q[i].x>0){ll x=Find(q[i].x),k=q[i].k;ans[i]=T.Ask(rt[x],1,1e9,k);}}for(ll i=t;i>=1;i--)if(ans[i])printf("%lld\n",ans[i]);return 0;
}

P5163-WD与地图【tarjan,整体二分,线段树合并】相关推荐

  1. E. Sign on Fence(整体二分 + 线段树维护区间最大连续 1 的个数)

    E. Sign on Fence 给定一个长度为nnn的数组aaa,1≤ai≤1091 \leq a_i \leq 10 ^ 91≤ai​≤109,有mmm次询问,每次给定l,r,kl, r, kl, ...

  2. 线段树分裂与合并 ----- P2824 [HEOI2016/TJOI2016]排序 [线段树分裂合并 OR 01序列排序+二分线段树]

    题目链接 题目大意: 对一个序列,每次按照升序或者降序排序序列某一段,问你最后的序列是什么? 解法1:二分+线段树 首先我们知道对一个01序列进行排序是很快的!我们只要知道里面有多少个1和多少个0,那 ...

  3. BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)

    题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...

  4. [Vani有约会]雨天的尾巴 (线段树合并)

    题目链接 Solution 树上差分+线段树合并. 在每个节点上维护一棵权值线段树. 然后如果需要修改 \(x,y\) 两点,则在 \(x\) 处和 \(y\) 处分别加上 \(1\) 的权值. 然后 ...

  5. 【BZOJ5469】[FJOI2018]领导集团问题(动态规划,线段树合并)

    [BZOJ5469][FJOI2018]领导集团问题(动态规划,线段树合并) 题面 BZOJ 洛谷 题解 题目就是让你在树上找一个最大的点集,使得两个点如果存在祖先关系,那么就要满足祖先的权值要小于等 ...

  6. 2021CCPC华为云挑战赛:HDU 7091 重叠的子串(SAM + 线段树合并)

    重叠的子串 给定一个长度为n(1≤∣s∣≤105)n(1 \le \mid s \mid \le 10 ^ 5)n(1≤∣s∣≤105)的只由小写字母构成的字符串sss,有m,(1≤m≤106)m, ...

  7. [2021.1.27多校省选模拟10]跑步(线段树合并)

    [2021.1.27多校省选模拟10]跑步 经典的树上启发式合并题目,维护对应子树的从当前点到子树内一个节点这个链待定,其他部分已经确定的方案数,这个东西按照对应点到根节点的路径点权和为下标存在一个权 ...

  8. 清明梦超能力者黄YY[树链剖分+扫描线,线段树合并]

    清明梦超能力者黄YY 题目连接 https://www.nowcoder.com/acm/contest/206/I 暂时有两种做法. 算法一 涉及:树链剖分,扫描线 在一个线段的情况下,我们可以把一 ...

  9. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree...

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

最新文章

  1. [FreeBSD] kvm下安装virtio驱动的freebsd
  2. linux 内核 scsi底层驱动程序,Linux系统下基于SCST的SCSI_Target驱动设计.doc
  3. 计算机的组成和Linux的发行版本介绍
  4. 语音处理入门——语音的声学处理
  5. 一键抠除路人甲,昇腾CANN带你识破神秘的“AI消除术”
  6. matlab程序里nbus=x的意思,MATLAB潮流程序(IEEE14 直角坐标 牛拉法)
  7. 在Android Studio中将Android工程变为Library使用
  8. ssas_通过SSAS透视图提高可读性
  9. 解决Vue-Router报错:vue-router.esm.js:17 [vue-router] <router-link>‘s tag prop is deprecated and has been
  10. libiconv_百度百科
  11. 双本振双输出后接八切一影响其它端口信号
  12. 微信小程序canvas2D全新API介绍
  13. go-项目配置govendor【详细教程】
  14. 深圳摇号验证码一输完就变的解决办法
  15. java 个人通讯录_java个人通讯录管理系统
  16. 价值投资如何判断市场是否高估
  17. Js 的防抖与节流代码分析
  18. Blender 3.5 面的操作(二)
  19. 论文翻译及笔记【Quantifying Societal Bias Amplification in Image Captioning】
  20. java 时区 不正确_Java中的时区不匹配

热门文章

  1. 无法定位程序输入点dxgiget_美国ABB TZIDC 智能定位器调试方法
  2. python基金会主席入门教程_Python基金会-文件IO操作,python,基础
  3. 小手拍拍机器人_幼儿园互动儿歌游戏,小朋友瞬间变听话!
  4. 10玩rust_C++工程师的Rust迁移之路(5)- 继承与组合 - 下
  5. python 正则匹配 条件太多怎么办_Python条件正则表达式
  6. sql datetime 排序_超全的数据库建表/SQL/索引规范,建议贴在工位上!
  7. 怎么删除mysql的所有文件内容_mysql删除全部数据库
  8. pearson相关系数_Pearson(皮尔逊)相关系数
  9. mysql 默认事务隔离级别_MySQL 事务隔离级别详解
  10. php phpmailer qq邮箱,QQ邮箱利用PHPmailer发送邮件