题解 CF1795G【Removal Sequences】
不妨考虑时间倒流。显然最后被删去的点一定是
最后我们会连出来一个偏序的 DAG。如果两个点
交上去之后你会发现 MLE 了。解决办法也很粗暴,将值域分成常数个区间分开求解即可。时间复杂度
#include<bits/stdc++.h>
#define ll long long
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rof(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
const int Maxn=1e5,B=1e4;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int T,n,m,a[Maxn+5],deg[Maxn+5],vis[Maxn+5]; ll ans;
vector<int> v[Maxn+5],w[Maxn+5];
bitset<B+5> f[Maxn+5];
queue<int> q;
inline void Clear()
{
For(i,1,n) vector<int>().swap(v[i]);
For(i,1,n) vector<int>().swap(w[i]);
For(i,1,n) vis[i]=0;
}
inline void Solve()
{
n=read(),m=read();
For(i,1,n) a[i]=read(),deg[i]=0;
For(i,1,m)
{
int a=read(),b=read();
v[a].push_back(b),v[b].push_back(a),deg[a]++,deg[b]++;
}
For(i,1,n) if(a[i]==0) q.push(i);
static int st[Maxn+5]; int top=0;
while(!q.empty())
{
int x=q.front(); q.pop(),vis[x]=1,st[++top]=x;
for(auto y:v[x]) if(!vis[y])
{
a[y]--,w[x].push_back(y);
if(!a[y]) q.push(y);
}
}
ans=1ll*n*(n-1)/2;
for(int l=1,r;l<=n;l=r+1)
{
r=min(l+B,n);
For(i,1,n) f[i].reset();
For(i,l,r) f[i][i-l]=1;
Rof(id,top,1)
{
int i=st[id]; for(auto j:w[i]) f[i]|=f[j];
int k=f[i].count(); ans-=k;
}
}
cout<<ans+n<<endl; Clear();
}
int main()
{
T=read();
while(T--) Solve();
return 0;
}