题解 小 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;
}