我是靠谱客的博主 光亮眼神,最近开发中收集的这篇文章主要介绍[二分答案 2-SAT验证 前缀后缀优化建图 线段树优化建图] Codeforces gym 100159 Facebook Hacker Cup 2012 I. Unfriending,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

二分答案 我们需要解决 对于一个点选了 一段不能选
这个裸建图肯定不行 那么我们用前后缀和线段树 优化建图
具体看代码 或 [二分答案 2-SAT验证 前后缀优化建图] Codeforces 587D #326 (Div. 1) D. Duff in Mafia

有一个细节 当冲突的个数超过一定大的值时是不可能有解的 这里dls教我说 1.2106 所以其实不用线段树也问题不大?

这个题只有两个点 一个还是样例 时限确实100s 但让我卡常数卡的
后来实在不行 只能援力爆发 参考了杜老师的代码 因为随机数据答案很小 所以杜老师的二分是这么写的

 while (l+1<r) {
   int md=(l+r)>>1;
   if (l<10&&r>10) md=10;
   if (check(md)) l=md; else r=md;
 }

上自己的代码吧

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> abcd;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
  return *p1++;
}
inline void read(int &x){
  char c=nc(),b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=5000005;
const int M=100005;

struct edge{
  int u,v,next;
}G[15000005];
int head[N],inum;
int _head[M],tmp;
inline void add(int u,int v){
  int p=++inum; G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
int pre[N],low[N],clk;
int scc[N],cnt; int Stack[N],pnt;
#define V G[p].v
inline void dfs(int u){
  pre[u]=low[u]=++clk; Stack[++pnt]=u;
  for (int p=head[u];p;p=G[p].next)
    if (!pre[V])
      dfs(V),low[u]=min(low[u],low[V]);
    else if (!scc[V])
      low[u]=min(low[u],pre[V]);
  if (low[u]==pre[u]){
    ++cnt;
    while (Stack[pnt]!=u) scc[Stack[pnt--]]=cnt; scc[Stack[pnt--]]=cnt; 
  }
}

int n,m,Tot;
int x[M],y[M],size[M],sum[M];
inline int pf(int idx,int t,int x){ return (n<<1)+(sum[idx-1]<<1)+x-1; }
inline int sf(int idx,int t,int x){ return (n<<1)+(sum[idx-1]<<1)+size[idx]+x-1; }

abcd ls[N];

inline bool Tarjan(){
  for (int i=0;i<Tot;i++) pre[i]=low[i]=scc[i]=0; pnt=cnt=clk=0;
  for (int i=0;i<Tot;i++)
    if (!pre[i])
      dfs(i);
  for (int i=0;i<2*n;i+=2)
    if (scc[i]==scc[i^1])
      return 0;
  return 1;
}

int rt[N];
inline void Build(int x,int l,int r){
  if (l==r){
    rt[x]=ls[l].second<<1|1; return;
  }
  rt[x]=Tot++; int mid=(l+r)>>1;
  Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);
  add(rt[x],rt[x<<1]); add(rt[x],rt[x<<1|1]);
}
int ql,qr,qp;
inline void Link(int x,int l,int r){
  if (ql<=l && r<=qr){
    add(qp,rt[x]); return;
  }
  int mid=(l+r)>>1;
  if (ql<=mid) Link(x<<1,l,mid);
  if (qr>mid) Link(x<<1|1,mid+1,r);
}

int Cnt=0;
int pos1[N],pos2[N];

ll TOTOT;
int CNTNT;
inline bool check(int x){
  TOTOT+=inum; CNTNT++;
  int cot=0,lim=1.2e6;
  for (int i=1;i<=n;i++){
    pos1[i]=lower_bound(ls+1,ls+i,abcd(ls[i].first-x+1,0))-ls;
    pos2[i]=lower_bound(ls+i,ls+n+1,abcd(ls[i].first+x,0))-ls-1;
    cot+=i-pos1[i]; 
  }
  if (cot>lim) return Cnt++,0;
  for (int i=1;i<=n;i++){
    ql=pos1[i]; qr=i-1; qp=ls[i].second<<1;
    if (ql<=qr) Link(1,1,n);
    ql=i+1; qr=pos2[i]; qp=ls[i].second<<1;
    if (ql<=qr) Link(1,1,n);
  }
  return Tarjan();
}

int vst[N];

int main(){
  int T,Case=0,a,b,p;
  freopen("t.in","r",stdin);
  freopen("t2.out","w",stdout);
  read(T);
  while (T--){
    printf("Case #%d: ",++Case);
    read(n); read(m);
    read(x[0]); read(a),read(b),read(p);
    for (int i=1;i<n;i++) x[i]=((ll)x[i-1]*a+b)%p;
    for (int i=0;i<n;i++) vst[i]=0;
    for (int i=1;i<=m;i++){
      read(size[i]),read(y[1]),read(a),read(b); vst[y[1]]=1;
      for (int j=2;j<=size[i];j++) y[j]=((ll)y[j-1]*a+b)%n,vst[y[j]]=1;
      sort(y+1,y+size[i]+1); size[i]=unique(y+1,y+size[i]+1)-y-1;
      for (int j=1;j<=size[i];j++){
    if (j-1) add(pf(i,0,j),pf(i,0,j-1));
    add(pf(i,0,j),y[j]<<1);
    if (j+1<=size[i]) add(sf(i,0,j),sf(i,0,j+1));
    add(sf(i,0,j),y[j]<<1);
      }
      for (int j=1;j<=size[i];j++){
    if (j-1) add(y[j]<<1|1,pf(i,0,j-1));
    if (j+1<=size[i]) add(y[j]<<1|1,sf(i,0,j+1));
      }
      sum[i]=sum[i-1]+size[i];
    }
    Tot=(n<<1)+(sum[m]<<1);
    for (int i=0;i<n;i++) if (!vst[i]) add(i<<1|1,i<<1); 
    for (int i=0;i<n;i++) ls[i+1]=abcd(x[i],i);
    sort(ls+1,ls+n+1);
    Build(1,1,n);
    int L=0,R=ls[n].first+1,MID;
    for (int i=0;i<2*n;i++) _head[i]=head[i]; tmp=inum;
    while (L+1<R){
      MID=(L+R)>>1;
      if (L<10 && R>10) MID=10;
      if (check(MID))
    L=MID;
      else
    R=MID;
      for (int i=0;i<2*n;i++) head[i]=_head[i]; inum=tmp;
    }
    printf("%dn",L);
    for (int i=0;i<Tot;i++) head[i]=0; inum=0;
  }
  //printf("%lld %dn",TOTOT,CNTNT);
  return 0;
}

最后

以上就是光亮眼神为你收集整理的[二分答案 2-SAT验证 前缀后缀优化建图 线段树优化建图] Codeforces gym 100159 Facebook Hacker Cup 2012 I. Unfriending的全部内容,希望文章能够帮你解决[二分答案 2-SAT验证 前缀后缀优化建图 线段树优化建图] Codeforces gym 100159 Facebook Hacker Cup 2012 I. Unfriending所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部