二分答案
对于一个点,肯定有一个区间里的点和它不能共存
这个可以用线段树优化建图,每个friend list最多只能删一个,用前缀优化建图
还要一些针对随机数据什么的trick才能过…比如二分中的那个特判
#include
#include
#include
#include
#include
using namespace std;
const int N=5000010;
int T,n,m,cnt,tot;
int G[N],vis[N],dfn[N],low[N],s[N],g[N],vst[N],ig,tp,it,imax;
struct edge{
int t,nx;
}E[N<<1];
pair<int,int> a[N];
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void rea(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
vectorint ,int> > b[N];
inline void addedge(int x,int y){
//cout<
E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;
}
void Build(int g,int l,int r){
if(l==r) return imax=max(imax,g),addedge(tot+g,a[l].second<<1|1);
int mid=l+r>>1;
Build(g<<1,l,mid); Build(g<<1|1,mid+1,r);
addedge(tot+g,tot+(g<<1)); addedge(tot+g,tot+(g<<1|1));
}
void link(int g,int L,int R,int l,int r,int x){
if(L==l && r==R) return addedge(x,tot+g);
int mid=L+R>>1;
if(r<=mid) link(g<<1,L,mid,l,r,x);
else if(l>mid) link(g<<1|1,mid+1,R,l,r,x);
else link(g<<1,L,mid,l,mid,x),link(g<<1|1,mid+1,R,mid+1,r,x);
}
void tarjan(int x){
dfn[x]=low[x]=++it; vis[x]=1; s[++tp]=x;
for(int i=G[x];i;i=E[i].nx){
if(!vis[E[i].t]) tarjan(E[i].t);
if(vis[E[i].t]!=2) low[x]=min(low[x],low[E[i].t]);
}
if(dfn[x]==low[x]){
int k; ++ig;
do{ k=s[tp--]; vis[k]=2; g[k]=ig; }while(k!=x && tp);
}
}
inline bool check(int x){
memset(G,0,sizeof(G));
memset(vis,0,sizeof(vis));
cnt=tp=ig=it=imax=0; tot=(n-1<<1|1)+1;
Build(1,0,n-1);
int cc=0;
for(int i=0;iif (!vst[i]) addedge(i<<1|1,i<<1);
for(int i=0,j=0;iwhile(a[i].first-a[j].first>=x) j++;
if(j1,0,n-1,j,i-1,a[i].second<<1),cc+=i-j;
}
if(cc>=1200000) return false;
for(int i=n-1,j=n-1;~i;i--){
while(a[j].first-a[i].first>=x) j--;
if(j>i) link(1,0,n-1,i+1,j,a[i].second<<1);
}
tot+=imax+1;
for(int i=1;i<=m;i++){
addedge(b[i][0].second<<1|1,tot);
addedge(tot+1,b[i][0].second<<1);
for(int j=1;j1<<1),tot+(j<<1));
addedge(tot+(j<<1|1),tot+(j-1<<1|1));
addedge(b[i][j].second<<1|1,tot+(j<<1));
addedge(tot+(j<<1|1),b[i][j].second<<1);
addedge(b[i][j].second<<1|1,tot+(j-1<<1|1));
addedge(tot+(j-1<<1),b[i][j].second<<1);
}
tot+=(b[i].size()<<1|1)+1;
}
for(int i=0;i<=tot;i++)
if(!vis[i]) tarjan(i);
for(int i=0;iif(g[i<<1]==g[i<<1|1]) return false;
return true;
}
int main(){
rea(T); int CASE=0;
while(T--){
memset(vst,0,sizeof(vst));
rea(n); rea(m); rea(a[0].first);
int x,y,p; rea(x); rea(y); rea(p);
for(int i=1;i1LL*a[i-1].first*x+y)%p;
for(int i=0;ifor(int i=1;i<=m;i++){
int size,x,y; rea(size);
b[i].resize(size);
rea(b[i][0].second); rea(x); rea(y);
b[i][0].second%=n;
for(int j=1;j1LL*b[i][j-1].second*x+y)%n;
for(int j=0;j1;
sort(b[i].begin(),b[i].end());
b[i].resize(unique(b[i].begin(),b[i].end())-b[i].begin());
}
sort(a,a+n);
int l=0,r=1e9,mid,ans=-1;
while(l<=r){
mid=l+r>>1;
if(l<10 && r>10) mid=10;
check(mid)?l=(ans=mid)+1:r=mid-1;
}
printf("Case #%d: %d\n",++CASE,ans);
}
return 0;
}