题解 小 G 的 DAG

传送门

显然是根号分治,问题是怎么分

因为这两种修改之间不太能合并,所以直接对询问分块的话无法在 \(O(n)\) 的复杂度内计算 \(\sqrt q\) 个修改的贡献
不过可以过掉只有一种修改的部分分
然而我证假了一个非常重要的结论,所以寄了
对于一次查询,只有最后一次操作 1 之后的操作 2 是有用的
无法理解我怎么证假的
所以对操作 1 分块,每次查询时 \(O(\sqrt q)\) 查一下所有能产生贡献的操作 2 的最小值即可
发现 bitset 开不下,所以每 \(2e4\) 个分别跑一遍
复杂度 \(O(\frac{n}{S_1}(n\frac{S_1}{\omega}+n\frac{q}{S_2}+qS_2))\)这为啥能过啊
唔三分调一下块长的话确实是可以过的,对卡常技巧有较高要求

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m, q;
int val[N];
pair<int, int> e[N];
vector<int> to[N], back[N];
struct que{int op, u, x;}qr[N];

namespace force{
	bool vis[N];
	void dfs(int u, pair<int, int> op) {
		vis[u]=1;
		if (op.fir&1) val[u]=op.sec;
		else val[u]=min(val[u], op.sec);
		for (auto v:to[u]) if (!vis[v]) dfs(v, op);
	}
	void solve() {
		for (int i=1,op,u,x; i<=q; ++i) {
			op=read();
			if (op<=2) {
				u=read(); x=read();
				for (int j=1; j<=n; ++j) vis[j]=0;
				dfs(u, {op, x});
			}
			else printf("%d\n", val[read()]);
		}
	}
}

namespace task1{
	bitset<1005> mask[N];
	struct opr{
		int op, x;
		opr(int a=0, int b=0){op=a, x=b;}
		inline opr operator + (opr b) {
			if (op==0) return b;
			else if (op==1) {
				if (b.op==1) return opr(1, b.x);
				else return opr(1, min(x, b.x));
			}
			else {
				if (b.op==1) return opr(1, b.x);
				else return opr(2, min(x, b.x));
			}
		}
	}op[N];
	// vector<pair<int, opr>> sta[N];
	int uni[N], tim[N], id[N], deg[N], ans[N], len, usiz;
	int que[N], l, r;
	void getmask() {
		// cout<<"getmask"<<endl;
		l=1; r=0;
		for (int i=1; i<=n; ++i) mask[i].reset(), deg[i]=0;
		for (int i=1; i<=m; ++i) ++deg[e[i].fir];
		for (int i=1; i<=usiz; ++i) mask[uni[i]][i]=1;
		for (int i=1; i<=n; ++i) if (!deg[i]) que[++r]=i;
		while (l<=r) {
			int u=que[l++];
			for (auto v:back[u]) {
				mask[v]|=mask[u];
				if (--deg[v]==0) que[++r]=v;
			}
		}
		// cout<<"return"<<endl;
	}
	void spread() {
		// cout<<"spread: "<<endl;
		l=1; r=0;
		for (int i=1; i<=n; ++i) deg[i]=0;
		for (int i=1; i<=m; ++i) ++deg[e[i].sec];
		for (int i=1; i<=n; ++i) if (!deg[i]) que[++r]=i;
		while (l<=r) {
			int u=que[l++];
			// sort(sta[u].begin(), sta[u].end(), [](pair<int, opr> a, pair<int, opr> b){return a.fir<b.fir;});
			// for (auto it:sta[u]) op[u]=op[u]+it.sec, tim[u]=it.fir;
			if (op[u].op==1) val[u]=op[u].x;
			else if (op[u].op==2) val[u]=min(val[u], op[u].x);
			for (auto v:to[u]) {
				// sta[v].pb({tim[u], op[u]});
				if (tim[u]<=tim[v]) op[v]=op[u]+op[v];
				else op[v]=op[v]+op[u];
				tim[v]=max(tim[u], tim[v]);
				if (--deg[v]==0) que[++r]=v;
			}
		}
		// cout<<"return"<<endl;
	}
	void solve() {
		// len=sqrt(q);
		len=1000;
		for (int i=1,op,u,x; i<=q; ++i) {
			op=read();
			if (op<=2) {
				u=read(); x=read();
				qr[i]={op, u, x};
			}
			else qr[i]={op, read(), 0};
		}
		for (int l=1,r; l<=q; l=r+1) {
			r=min(q, l+len-1); usiz=0;
			for (int i=l; i<=r; ++i) if (qr[i].op==3) uni[++usiz]=qr[i].u;
			sort(uni+1, uni+usiz+1);
			usiz=unique(uni+1, uni+usiz+1)-uni-1;
			// cout<<"usiz: "<<usiz<<endl;
			for (int i=1; i<=usiz; ++i) id[uni[i]]=i;
			getmask();
			for (int i=1; i<=n; ++i) tim[i]=0, op[i]={0, 0}; //, sta[i].clear();
			for (int i=l; i<=r; ++i) {
				// cout<<"i: "<<i<<endl;
				if (qr[i].op==3) {
					for (int j=l; j<i; ++j) if (qr[j].op<=2 && mask[qr[j].u][id[qr[i].u]]) {
						if (qr[j].op==1) val[qr[i].u]=qr[j].x;
						else if (qr[j].op==2) val[qr[i].u]=min(val[qr[i].u], qr[j].x);
					}
					ans[i]=val[qr[i].u];
				}
				else op[qr[i].u]=op[qr[i].u]+opr(qr[i].op, qr[i].x), tim[qr[i].u]=i;
			}
			spread();
		}
		for (int i=1; i<=q; ++i) if (qr[i].op==3) printf("%d\n", ans[i]);
	}
}

namespace task{
	bitset<20000> mask[N];
	struct op1{int tim, u, x;}sta[N];
	int ans[N], val[N], tim[N], bel[N], deg[N], ord[N], f[325][20005], len, top, tot;
	void init() {
		queue<int> q;
		for (int i=1; i<=n; ++i) deg[i]=0;
		for (int i=1; i<=m; ++i) ++deg[e[i].sec];
		for (int i=1; i<=n; ++i) if (!deg[i]) q.push(i);
		while (q.size()) {
			int u=q.front(); q.pop();
			ord[++tot]=u;
			for (auto v:to[u]) if (--deg[v]==0) q.push(v);
		}
	}
	void spread2() {
		// queue<int> q;
		// for (int i=1; i<=n; ++i) deg[i]=0;
		// for (int i=1; i<=m; ++i) ++deg[e[i].sec];
		// for (int i=1; i<=n; ++i) if (!deg[i]) q.push(i);
		// while (q.size()) {
		// 	int u=q.front(); q.pop();
		// 	for (auto v:to[u]) {
		// 		val[v]=min(val[v], val[u]);
		// 		if (--deg[v]==0) q.push(v);
		// 	}
		// }
		for (int i=1; i<=n; ++i)
			for (auto v:to[ord[i]])
				val[v]=min(val[v], val[ord[i]]);
	}
	int qmin(int l, int r, int id) {
		int sid=bel[l], eid=bel[r], ans=INF;
		if (sid==eid) {
			for (int i=l; i<=r; ++i) if (qr[i].op==2 && mask[qr[i].u][id]) ans=min(ans, qr[i].x);
			return ans;
		}
		for (int i=l; bel[i]==sid; ++i) if (qr[i].op==2 && mask[qr[i].u][id]) ans=min(ans, qr[i].x);
		for (int i=sid+1; i<eid; ++i) ans=min(ans, f[i][id]);
		for (int i=r; bel[i]==eid; --i) if (qr[i].op==2 && mask[qr[i].u][id]) ans=min(ans, qr[i].x);
		return ans;
	}
	void spread1() {
		for (int i=1; i<=top; ++i) tim[sta[i].u]=sta[i].tim, val[sta[i].u]=sta[i].x;
		// queue<int> q;
		// for (int i=1; i<=n; ++i) deg[i]=0;
		// for (int i=1; i<=m; ++i) ++deg[e[i].sec];
		// for (int i=1; i<=n; ++i) if (!deg[i]) q.push(i);
		// while (q.size()) {
		// 	int u=q.front(); q.pop();
		// 	for (auto v:to[u]) {
		// 		if (tim[v]<tim[u]) val[v]=val[u], tim[v]=tim[u];
		// 		if (--deg[v]==0) q.push(v);
		// 	}
		// }
		for (int i=1; i<=n; ++i) if (tim[ord[i]])
			for (auto v:to[ord[i]])
				if (tim[v]<tim[ord[i]])
					val[v]=val[ord[i]], tim[v]=tim[ord[i]];
		top=0;
	}
	void getmask(int l, int r) {
		// queue<int> q;
		for (int i=1; i<=n; ++i) mask[i].reset(), deg[i]=0;
		// for (int i=1; i<=m; ++i) ++deg[e[i].fir];
		for (int i=l; i<=r; ++i) mask[i][i-l]=1;
		// for (int i=1; i<=n; ++i) if (!deg[i]) q.push(i);
		// while (q.size()) {
		// 	int u=q.front(); q.pop();
		// 	bool tem=1;
		// 	if (mask[u].none()) tem=0;
		// 	for (auto v:back[u]) {
		// 		if (tem) mask[v]|=mask[u];
		// 		if (--deg[v]==0) q.push(v);
		// 	}
		// }
		for (int i=n; i; --i) if (mask[ord[i]].any()) {
			for (auto v:back[ord[i]])
				mask[v]|=mask[ord[i]];
		}
	}
	void solve() {
		len=1500;
		for (int i=1,op,u,x; i<=q; ++i) {
			op=read();
			if (op<=2) {
				u=read(); x=read();
				qr[i]={op, u, x};
			}
			else qr[i]={op, read(), 0};
		}
		init();
		for (int i=1; i<=q; ++i) bel[i]=(i-1)/len+1;
		for (int l=1,r; l<=n; l=r+1) {
			r=min(n, l+20000-1); top=0;
			cerr<<"lr: "<<l<<' '<<r<<endl;
			getmask(l, r);
			for (int tl=1,tr,id=1; tl<=q; tl=tr+1,++id) {
				tr=min(q, tl+len-1);
				for (int i=1; i<=n; ++i) val[i]=INF;
				for (int i=tl; i<=tr; ++i) if (qr[i].op==2) val[qr[i].u]=min(val[qr[i].u], qr[i].x);
				spread2();
				for (int i=l; i<=r; ++i) f[id][i-l]=val[i];
			}
			for (int i=1; i<=n; ++i) tim[i]=val[i]=0;
			for (int i=1; i<=q; ++i) {
				if (qr[i].op==1) {
					sta[++top]={i, qr[i].u, qr[i].x};
					if (top==len) spread1();
				}
				else if (qr[i].op==3 && l<=qr[i].u&&qr[i].u<=r) {
					int lst=tim[qr[i].u]; ans[i]=val[qr[i].u];
					for (int j=1; j<=top; ++j) if (mask[sta[j].u][qr[i].u-l]) ans[i]=sta[j].x, lst=sta[j].tim;
					ans[i]=min(ans[i], qmin(lst+1, i, qr[i].u-l));
				}
			}
		}
		for (int i=1; i<=q; ++i) if (qr[i].op==3) printf("%d\n", ans[i]);
	}
}

signed main()
{
	freopen("dag.in", "r", stdin);
	freopen("dag.out", "w", stdout);

	n=read(); m=read(); q=read();
	for (int i=1,u,v; i<=m; ++i) {
		u=read(); v=read();
		e[i]={u, v};
		to[u].pb(v); back[v].pb(u);
	}
	// if (n<=5000 && m<=5000) force::solve();
	// else task1::solve();
	task::solve();
	
	return 0;
}
posted @ 2022-03-05 17:26  Administrator-09  阅读(1)  评论(0编辑  收藏  举报