zoukankan      html  css  js  c++  java
  • WD与地图题解

    神仙题……有整体二分,线段树合并qwq。

    首先要将删边改为加边,倒叙处理操作。

    我们要使用整体二分处理一条边是在什么时候才让边的两端在同一个强连通分量里。对于每一次solve,我们传入二分的两端和包含需要处理的边的 vector 数组。将在 mid 前出现的边建出一张图,然后在上面跑一遍 tarjan 。然后将 vector 内已经在同一个强连通分量里并且出现早于 mid 的边丢到左区间,其余丢到右区间进行处理。

    每次跑 tarjan 的时候进行缩点,将在一个强连通分量内的点使用可撤销并查集维护到一起。即相当于一个强连通分量使用他们的祖先来替代。跑完 tarjan 后将并查集保留,图删除。容易发现丢到左区间处理的边进行缩点之后其实只是一个点集。所以并不会出现漏掉强连通分量的问题。

    处理完这些后与询问一起排序处理,遇到边则并查集连边,当然这里是不必须使用可撤销并查集的,并且合并并查集的同时要进行线段树合并,来维护保存了并查集内元素的权值线段树,使用动态开点。查询的时候使用线段树上二分即可。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <vector>
    #include <queue>
    #define int long long
    using namespace std;
    
    int read()
    {
    	int a = 0,x = 1;char ch = getchar();
    	while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
    	while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
    	return a*x;
    }
    const int N=1e6+7;
    int n,m,q,s[N],ans[N];
    struct edge{
    	int u,v,tim;
    }E[N];
    struct quer{
    	int op,a,b,tim;
    }Q[N],cal[N];
    map<pair<int,int>,int>mp;
    struct DSU{
    	int fa[N],siz[N],top,stk[N];
    	void init(int n) {for(int i = 1;i <= n;i ++) fa[i] = i,siz[i] = 1;}
    	int find(int s) {return fa[s] == s ? s : find(fa[s]);}
    	void merge(int a,int b)
    	{
    		a = find(a),b = find(b);
    		if(a == b) return ;
    		if(siz[a] > siz[b]) swap(a,b);
    		fa[a] = b,siz[b] += siz[a];
    		stk[++top] = a;
    	}
    	void del(int cur)
    	{
    		while(top > cur) {
    			siz[fa[stk[top]]] -= siz[stk[top]];
    			fa[stk[top]] = stk[top];--top;
    		}
    	}
    }uni;
    struct TARJAN{
    	int head[N],go[N],nxt[N],cnt;
    	int low[N],dfn[N],ins[N],stk[N],top;
    	vector<int>point;
    	void add(int u,int v) {
    		if(!head[u]) point.push_back(u);
    		point.push_back(v);
    		go[++cnt] = v;nxt[cnt] = head[u];
    		head[u] = cnt;
    	}
    	void clear() {
    		for(int u:point) ins[u] = dfn[u] = low[u] = head[u] = 0;cnt = 0;
    		point.clear();top = 0;
    	}
    	void tarjan(int u) {
    		dfn[u] = low[u] = ++cnt;
    		stk[++top] = u,ins[u] = 1;
    		for(int e = head[u];e;e = nxt[e]) {
    			int v = go[e];
    			if(!dfn[v]) {
    				tarjan(v);
    				low[u] = min(low[u],low[v]);
    			} else if(ins[v]) low[u] = min(low[u],dfn[v]);
    		}
    		if(dfn[u] == low[u]) {
    			do{
    				uni.merge(u,stk[top]);
    				ins[stk[top]] = 0;
    			}while(stk[top--] != u);
    		}
    	}
    	void work() {cnt=0;for(int i:point) if(!dfn[i]) tarjan(i);}
    }tar;
    
    void solve(int l,int r,vector<int>d)
    {
    //	printf("l=%d,r=%d
    ",l,r);
    	if(d.empty()) return ;
    	if(l == r) {for(int u:d) E[u].tim = l;return ;}
    	int mid = l+r>>1,cur = uni.top;
    	for(int i:d) {
    		if(E[i].tim <= mid) tar.add(uni.find(E[i].u),uni.find(E[i].v));
    	}
    	tar.work();	tar.clear();
    	vector<int>dd1,dd2;
    	for(int i:d) {
    		int u = uni.find(E[i].u),v = uni.find(E[i].v);
    		if(u == v && E[i].tim <= mid) dd1.push_back(i);
    		else dd2.push_back(i);
    	}
    	solve(mid+1,r,dd2);uni.del(cur);solve(l,mid,dd1);
    }
    
    struct SBT{
    	int tre[N<<3],ls[N<<3],rs[N<<3],tot,rt[N],siz[N<<3];
    	void modify(int &root,int l,int r,int p,int x)
    	{
    		if(!root) root = ++tot;int mid = l+r>>1;
    		if(l == r) {tre[root] += x*p,siz[root] += x;return ;}
    		if(p <= mid) modify(ls[root],l,mid,p,x);
    		else modify(rs[root],mid+1,r,p,x);
    		tre[root] = tre[ls[root]] + tre[rs[root]];
    		siz[root] = siz[ls[root]] + siz[rs[root]];
    	}
    	int merge(int a,int b)
    	{
    		if(!a || !b) return a+b;
    		tre[a] += tre[b];siz[a] += siz[b];
    		ls[a] = merge(ls[a],ls[b]),rs[a] = merge(rs[a],rs[b]);
    		return a;
    	}
    	int query(int root,int l,int r,int x)
    	{
    		if(l == r) return min(x,siz[root])*l;int mid = l+r>>1;
    		if(x == siz[rs[root]]) return tre[rs[root]];
    		if(x < siz[rs[root]]) return query(rs[root],mid+1,r,x);
    		if(x > siz[rs[root]]) return tre[rs[root]] + query(ls[root],l,mid,x-siz[rs[root]]);
    	}
    
    	void Merge(int a,int b) {
    		rt[uni.find(a)] = merge(rt[a],rt[b]);
    	}
    	void modify(int root,int x,int op)	{
    		modify(rt[root],1,(int)(1e9),x,op);
    	}
    }ds;
    bool cmp(quer a,quer b) {return a.tim!=b.tim?a.tim < b.tim:a.op<b.op;}
    signed main()
    {
    	// freopen("random.in","r",stdin);
    	// freopen("sol.out","w",stdout);
    	n = read(),m = read(),q = read();uni.init(n);
    	for(int i = 1;i <= n;i ++) s[i] = read();
    	for(int i = 1;i <= m;i ++) {
    		E[i].u = read(),E[i].v = read();
    		mp[make_pair(E[i].u,E[i].v)] = i;
    	}
    	for(int i = 1;i <= q;i ++) {
    		Q[i].op = read(),Q[i].a = read(),Q[i].b = read(),Q[i].tim = q-i+1;
    		if(Q[i].op == 1) {
    			E[mp[make_pair(Q[i].a,Q[i].b)]].tim = q-i+1;
    		} else if(Q[i].op == 2) s[Q[i].a] += Q[i].b;
    	}
    	vector<int>dd;
    	for(int i = 1;i <= m;i ++) dd.push_back(i);
    	solve(0,q+1,dd);int tot = m;//return 0;
    	for(int i = 1;i <= m;i ++) {
    		cal[i].op = 1,cal[i].tim = E[i].tim,cal[i].a = E[i].u,cal[i].b = E[i].v;
    	}
    	for(int i = 1;i <= q;i ++) {
    		if(Q[i].op == 1) continue;
    		cal[++tot] = Q[i];
    	}
    	for(int i = 1;i <= n;i ++) ds.modify(i,s[i],1);
    	sort(cal+1,cal+1+tot,cmp);uni.init(n);
    	for(int i = 1;i <= tot;i ++) {
    		if(cal[i].op == 1) {
    			int a = uni.find(cal[i].a),b = uni.find(cal[i].b);
    			uni.merge(a,b);if(a != b) ds.Merge(a,b);
    		} else if(cal[i].op == 2) {
    			int a = uni.find(cal[i].a),b = cal[i].a;
    			ds.modify(a,s[b],-1);
    			s[b] -= cal[i].b;
    			ds.modify(a,s[b],1);
    		} else {
    			int a = uni.find(cal[i].a),b = cal[i].b;
    			ans[i] = ds.query(ds.rt[a],1,(int)(1e9),b);
    		}
    	}
    	for(int i = tot;i >= 1;i --) if(ans[i]) printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    UCloud-201809-001:Redis服务未授权访问漏洞安全预警
    php框架tp3.2.3和js写的微信分享功能心得,分享的标题内容图片自定义
    一键分享到QQ空间、QQ好友、新浪微博、微信代码
    ArcGIS10.x Engine直连提示连接超时ORA-12170 来自:http://www.iarcgis.com/?p=1004
    ArcGIS Engine三维动画开发 来自:http://www.iarcgis.com/?p=826
    ArcGIS Engine断开其他ArcSDE用户连接的解决方案
    ARCGIS 10.0破解版安装过程error 1606 和error 1316问题 及安装流程
    教你如何查看CAD文件是哪个版本的来自http://blog.sina.com.cn/s/blog_4c9fa4dd0101il1v.html
    C# DataGridView,右键单击RowHeader时显示右键菜单怎么做?
    C#控制定位Word光标移动到任意行或者最后一行,取得光标位置等操作
  • 原文地址:https://www.cnblogs.com/nao-nao/p/14925219.html
Copyright © 2011-2022 走看看