题解 【SR2.5-T4】【第二次月面战争】
题解
先考虑一个简化的问题:
其实这玩意有两种思路,貌似都是对的(
想法
思路一
考虑让所有人同时沿着最短路向神社走去。可能发生的最糟糕的情况是,两个人挤占了同一个点,但是我们不知道他们什么时候相撞。但是事实上我们根本不需要考虑相撞的地点。只要假想一个时间轴,我们现在将第
至于为什么正确,感性理解吧。一个人
思路二
刚刚那个思路是屑波(@离散小波变换° )想出来的,可谓是非常难以理解()下面的思路是
考虑按照
事实上,出题人写了两个程序的暴力代码并且进行了一些对拍,并没有拍出不同的数据点。可以验证这两种思路都是对的。下面考虑如何实现。
求解
两种做法都可以用
思路一
我们需要动态插入/删除一个人,并且找到最靠后的那个人。一种可行的做法是,维护一个数列
插入一个人
考虑如何去快速查询、快速区间修改。我们用一棵线段树维护
复杂度是
思路二
为了方便操作,我们使用值域线段树,用来维护每个
具体操作非常简单,就不细讲了(
顺带一提,
参考代码
#include<bits/stdc++.h>
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
typedef long long LL;
const int INF =2147483647;
const int SIZ =1e6;
char buf[SIZ],*p1,*p2;
char readc(){
if(p1==p2) p1=buf,p2=buf+fread(buf,1,SIZ,stdin);
return *p1++;
}
int qread(){
int w=1,c,r=0;
while((c=readc())> '9'||c< '0') w=(c=='-'?-1:1); r=c-'0';
while((c=readc())>='0'&&c<='9') r=r*10+c-'0';
return r*w;
}
const int MAXN =1.05e6+3,MAXM=1.2e6+3;
namespace Gra{
int H[MAXN],V[MAXM],N[MAXM],t,D[MAXN]; bool F[MAXN];
void add(int u,int v){V[++t]=v,N[t]=H[u],H[u]=t;}
queue <int> Q;
void bfs(int u){
Q.push(u); while(!Q.empty()){
int a=Q.front(); Q.pop(); for(int i=H[a],b;i;i=N[i]){
if(!F[b=V[i]]) F[b]=true,Q.push(b),D[b]=D[a]+1;
}
}
}
}
int n,l,m,q,t,C[MAXN];
namespace Seg{
unsigned int W[MAXN*2],T[MAXN*2],M[MAXN*2],F[MAXN],w,t;
inline void inc(unsigned int p){
if(!F[p]) M[p|n]+=p; ++F[p],p|=n; ++M[p];
up(1,l,i){
if(p&1) ++T[p^1],++M[p^1]; M[p>>1]=max(M[p],M[p^1])+T[p>>1]; p>>=1;
}
}
inline void dec(unsigned int p){
--F[p];if(!F[p]) M[p|n]-=p; p|=n; --M[p];
up(1,l,i){
if(p&1) --T[p^1],--M[p^1]; M[p>>1]=max(M[p],M[p^1])+T[p>>1]; p>>=1;
}
}
}
bool O[MAXN];
int main(){
n=qread(),m=qread(),q=qread(),t=qread();
for(l=1;(1<<l)<=n;++l); n=1<<l;
up(1,m,i){int u=qread(),v=qread();Gra::add(v,u);}
Gra::D[t]=1,Gra::F[t]=true,Gra::bfs(t);
up(1,q,i){
int x=qread(); O[x]?Seg::dec(Gra::D[x]):Seg::inc(Gra::D[x]);
O[x]^=1,printf("%d\n",Seg::M[1]-1);
}
return 0;
}