• 2019.6.1 模拟赛——[ 费用流 ][ 数位DP ][ 计算几何 ]


    第一题:http://codeforces.com/contest/1061/problem/E

      把点集分成不相交的,然后跑费用流即可。然而错了一个点。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    int Mn(int a,int b){return a<b?a:b;}
    const int N=1505,M=N*8,INF=N;
    int n,tot,hd[N],xnt=1,to[M],nxt[M],cap[M],w[M];
    int dis[N],info[N],pre[N]; bool ins[N];
    int S,T,flow,val,ans; bool fg;
    queue<int> q;
    void add(int x,int y,int z,int k)
    {
      to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;
      cap[xnt]=z; w[xnt]=k;
      to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;
      cap[xnt]=0; w[xnt]=-k;
    }
    namespace I{
      const int N=505,M=N<<1;
      int c[N],hd[N],xnt,to[M],nxt[M],fa[N];
      int h2[N],xt2,t2[M],nt2[M];
      int lm[N],q[N],he,tl,tmp;
      void ad1(int x,int y)
      {to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
      void ad2(int x,int y)
      {t2[++xt2]=y;nt2[xt2]=h2[x];h2[x]=xt2;}
      void ini_dfs(int cr,int f)
      {
        fa[cr]=f;
        for(int i=hd[cr],v;i;i=nxt[i])
          if((v=to[i])!=f) ini_dfs(v,cr);
      }
      void dfs(int cr)
      {
        add(tot,cr,1,c[cr]);
        for(int i=hd[cr],v;i;i=nxt[i])
          if((v=to[i])!=fa[cr])
        {
          if(lm[v]){q[++tl]=v; tmp-=lm[v];}
          else dfs(v);
        }
      }
      void ini_dfs2(int cr,int f)
      {
        fa[cr]=f;
        for(int i=h2[cr],v;i;i=nt2[i])
          if((v=t2[i])!=f) ini_dfs2(v,cr);
      }
      void dfs2(int cr)
      {
        add(cr,tot,1,0);
        for(int i=h2[cr],v;i;i=nt2[i])
          if((v=t2[i])!=fa[cr])
        {
          if(lm[v]){q[++tl]=v; tmp-=lm[v];}
          else dfs2(v);
        }
      }
      void solve()
      {
        int s0=rdn(),s1=rdn();
        for(int i=1;i<=n;i++)c[i]=rdn();
        for(int i=1,u,v;i<n;i++)
          u=rdn(),v=rdn(),ad1(u,v),ad1(v,u);
        for(int i=1,u,v;i<n;i++)
          u=rdn(),v=rdn(),ad2(u,v),ad2(v,u);
        int Q=rdn();
        for(int i=1;i<=Q;i++)
          {int d=rdn(); lm[d]=rdn();}
        val=lm[s0];
        he=tl=0; q[++tl]=s0; ini_dfs(s0,0);
        while(he<tl)
          {
        int k=q[++he]; tmp=lm[k];
        tot++; dfs(k); add(S,tot,tmp,0);
          }
        memset(lm,0,sizeof lm); Q=rdn();
        for(int i=1;i<=Q;i++)
          {int d=rdn(); lm[d]=rdn();}
        he=tl=0; q[++tl]=s1; fa[s1]=0; ini_dfs2(s1,0);
        while(he<tl)
          {
        int k=q[++he]; tmp=lm[k];
        tot++; dfs2(k); add(tot,T,tmp,0);
          }
        if(val!=lm[s1])fg=1;
      }
    }
    bool spfa()
    {
      memset(dis,-4,sizeof dis); dis[S]=0;
      info[S]=INF; info[T]=0; q.push(S); ins[S]=1;
      while(q.size())
        {
          int k=q.front(); q.pop(); ins[k]=0;
          for(int i=hd[k],v;i;i=nxt[i])
        if(cap[i]&&dis[v=to[i]]<dis[k]+w[i])
          {
            dis[v]=dis[k]+w[i]; pre[v]=i;
            info[v]=Mn(info[k],cap[i]);
            if(!ins[v])ins[v]=1,q.push(v);
          }
        }
      return info[T];
    }
    void ek()
    {
      int k=info[T]; flow+=k;
      for(int i=pre[T];i;i=pre[to[i^1]])
        { cap[i]-=k; cap[i^1]+=k; ans+=k*w[i];}
    }
    int main()
    {
      freopen("w.in","r",stdin);
      freopen("w.out","w",stdout);
      tot=n=rdn(); S=0; T=++tot; I::solve();
      if(fg){puts("-1");return 0;}
      while(spfa())ek();
      if(flow==val)printf("%d
    ",ans);
      else puts("-1");
      return 0;
    }

      后来发现是题目里写了 “每个人的条件不会自相矛盾” ,但那个点却自相矛盾了。

      判一下即可。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    int Mn(int a,int b){return a<b?a:b;}
    const int N=1505,M=N*8,INF=N;
    int n,tot,hd[N],xnt=1,to[M],nxt[M],cap[M],w[M];
    int dis[N],info[N],pre[N]; bool ins[N];
    int S,T,flow,val,ans; bool fg;
    queue<int> q;
    void add(int x,int y,int z,int k)
    {
      to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;
      cap[xnt]=z; w[xnt]=k;
      to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;
      cap[xnt]=0; w[xnt]=-k;
    }
    namespace I{
      const int N=505,M=N<<1;
      int c[N],hd[N],xnt,to[M],nxt[M],fa[N];
      int h2[N],xt2,t2[M],nt2[M];
      int lm[N],q[N],he,tl,tmp;
      void ad1(int x,int y)
      {to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
      void ad2(int x,int y)
      {t2[++xt2]=y;nt2[xt2]=h2[x];h2[x]=xt2;}
      void ini_dfs(int cr,int f)
      {
        fa[cr]=f;
        for(int i=hd[cr],v;i;i=nxt[i])
          if((v=to[i])!=f) ini_dfs(v,cr);
      }
      void dfs(int cr)
      {
        add(tot,cr,1,c[cr]);
        for(int i=hd[cr],v;i;i=nxt[i])
          if((v=to[i])!=fa[cr])
        {
          if(lm[v]){q[++tl]=v; tmp-=lm[v];}
          else dfs(v);
        }
      }
      void ini_dfs2(int cr,int f)
      {
        fa[cr]=f;
        for(int i=h2[cr],v;i;i=nt2[i])
          if((v=t2[i])!=f) ini_dfs2(v,cr);
      }
      void dfs2(int cr)
      {
        add(cr,tot,1,0);
        for(int i=h2[cr],v;i;i=nt2[i])
          if((v=t2[i])!=fa[cr])
        {
          if(lm[v]){q[++tl]=v; tmp-=lm[v];}
          else dfs2(v);
        }
      }
      void solve()
      {
        int s0=rdn(),s1=rdn();
        for(int i=1;i<=n;i++)c[i]=rdn();
        for(int i=1,u,v;i<n;i++)
          u=rdn(),v=rdn(),ad1(u,v),ad1(v,u);
        for(int i=1,u,v;i<n;i++)
          u=rdn(),v=rdn(),ad2(u,v),ad2(v,u);
        int Q=rdn();
        for(int i=1;i<=Q;i++)
          {int d=rdn(); lm[d]=rdn();}
        val=lm[s0];
        he=tl=0; q[++tl]=s0; ini_dfs(s0,0);
        while(he<tl)
          {
        int k=q[++he]; tmp=lm[k];
        tot++; dfs(k); if(tmp<0){fg=1;break;}
        add(S,tot,tmp,0);
          }
        if(fg)return;
        memset(lm,0,sizeof lm); Q=rdn();
        for(int i=1;i<=Q;i++)
          {int d=rdn(); lm[d]=rdn();}
        he=tl=0; q[++tl]=s1; fa[s1]=0; ini_dfs2(s1,0);
        while(he<tl)
          {
        int k=q[++he]; tmp=lm[k];
        tot++; dfs2(k); if(tmp<0){fg=1;break;}
        add(tot,T,tmp,0);
          }
        if(val!=lm[s1])fg=1;
      }
    }
    bool spfa()
    {
      memset(dis,-4,sizeof dis); dis[S]=0;
      info[S]=INF; info[T]=0; q.push(S); ins[S]=1;
      while(q.size())
        {
          int k=q.front(); q.pop(); ins[k]=0;
          for(int i=hd[k],v;i;i=nxt[i])
        if(cap[i]&&dis[v=to[i]]<dis[k]+w[i])
          {
            dis[v]=dis[k]+w[i]; pre[v]=i;
            info[v]=Mn(info[k],cap[i]);
            if(!ins[v])ins[v]=1,q.push(v);
          }
        }
      return info[T];
    }
    void ek()
    {
      int k=info[T]; flow+=k;
      for(int i=pre[T];i;i=pre[to[i^1]])
        { cap[i]-=k; cap[i^1]+=k; ans+=k*w[i];}
    }
    int main()
    {
      freopen("w.in","r",stdin);
      freopen("w.out","w",stdout);
      tot=n=rdn(); S=0; T=++tot;
      I::solve();
      if(fg){puts("-1");return 0;}
      while(spfa())ek();
      if(flow==val)printf("%d
    ",ans);
      else puts("-1");
      return 0;
    }
    View Code

    第二题:http://codeforces.com/contest/1045/problem/H

      考场上不会做……

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    using namespace std;
    const int N=105,mod=1e9+7;
    int upt(int x){while(x>=mod)x-=mod;while(x<0)x+=mod;return x;}
    
    int n,m,A,B,C,D,ans;char s1[N],s2[N],s[N];
    struct Node{
      int x,y;
      Node(int x=0,int y=0):x(x),y(y) {}
      bool operator< (const Node &b)const
      {return x==b.x?y<b.y:x<b.x;}
    };
    map<Node,int> dp[N][2][N][N],mp[N][2][N][N];
    void init()
    {
      memcpy(s,s1,sizeof s1);
      for(int i=1;i<=n;i++)
        if(s[i]=='1'){s[i]='0';break;}
        else s[i]='1';
    }
    int dfs(int t,bool fx,int a,int b,int c,int d)
    {
      if(a<0||b<0||c<0||d<0)return 0;
      Node cr=Node(c,d);
      if(dp[t][fx][a][b].count(cr))
        {
          return dp[t][fx][a][b][cr];
        }
      if(!t) return dp[t][fx][a][b][cr]=((!a)&&(!b)&&(!c)&&(!d));
      int ret=0;
      if(!fx)
        {
          ret=upt(ret+dfs(t-1,0,a-1,b,c,d));
          ret=upt(ret+dfs(t-1,1,a,b-1,c,d));
        }
      else
        {
          ret=upt(ret+dfs(t-1,0,a,b,c-1,d));
          ret=upt(ret+dfs(t-1,1,a,b,c,d-1));
        }
      dp[t][fx][a][b][cr]=ret; return ret;
    }
    int dfsx(int t,bool fx,int a,int b,int c,int d)
    {
      if(a<0||b<0||c<0||d<0)return 0;
      Node cr=Node(c,d);
      if(mp[t][fx][a][b].count(cr))
        {
          return mp[t][fx][a][b][cr];
        }
      if(!t)
        {
          int ret=((!a)&&(!b)&&(!c)&&(!d));
          return mp[t][fx][a][b][cr]=ret;
        }
      if(s[t]=='0')
        {
          if(!fx)a--; else c--;
          int ret=dfsx(t-1,0,a,b,c,d);
          return mp[t][fx][a][b][cr]=ret;
        }
      int ta=a,tb=b,tc=c,td=d; if(!fx)tb--; else td--;
      int ret=dfsx(t-1,1,ta,tb,tc,td);
      ta=a; tb=b; tc=c; td=d;
      if(!fx)a--; else c--;
      ret=upt(ret+dfs(t-1,0,a,b,c,d));//
      mp[t][fx][a][b][cr]=ret; return ret;
    }
    void solve(int lm)
    {
      for(int t=0;t<=lm;t++)
        for(int fx=0;fx<=1;fx++)
          for(int i=0;i<=A;i++)
        for(int j=0;j<=B;j++)
          {
            dp[t][fx][i][j].clear();
            mp[t][fx][i][j].clear();
          }
      for(int t=1;t<lm;t++)
        {
          ans=upt(ans+dfs(t-1,1,A,B,C,D));
        }
      ans=upt(ans+dfsx(lm-1,1,A,B,C,D));
    }
    int main()
    {
      freopen("i.in","r",stdin);
      freopen("i.out","w",stdout);
      scanf("%s",s1+1); scanf("%s",s2+1);
      n=strlen(s1+1); m=strlen(s2+1);
      reverse(s1+1,s1+n+1); reverse(s2+1,s2+m+1);
      scanf("%d%d%d%d",&A,&B,&C,&D);
      init(); solve(n); ans=upt(-ans);
      memcpy(s,s2,sizeof s2);
      solve(m); printf("%d
    ",ans);
      return 0;
    }

      后来得知 “随便填” 的方案可以用组合数算。就是通过 01 和 10 的个数可以知道 0 和 1 分成了几段。

      仔细一想,直接搜,不用记忆化就行。

      不知为何自己的代码必须特判 if( B<C-1 || B>C ) puts(" 0 ");

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int Mx(int a,int b){return a>b?a:b;}
    int Mn(int a,int b){return a<b?a:b;}
    const int N=1e5+5,mod=1e9+7;
    int upt(int x){while(x>=mod)x-=mod;while(x<0)x+=mod;return x;}
    int pw(int x,int k)
    {int ret=1;while(k){if(k&1)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=1;}return ret;}
    
    int n,A,B,C,D,jc[N],jcn[N];
    char s[N],s1[N],s2[N];
    struct Node{
      int a,b,c,d;
      Node(int a=0,int b=0,int c=0,int d=0):a(a),b(b),c(c),d(d) {}
      bool operator< (const Node &v)const
      {
        if(a!=v.a)return a<v.a; if(b!=v.b)return b<v.b;
        if(c!=v.c)return c<v.c; return d<v.d;
      }
    };
    void init()
    {
      memcpy(s,s1,sizeof s1);
      for(int i=1;i<=n;i++)
        if(s[i]=='0')s[i]='1';
        else {s[i]='0';if(i==n)n--;break;}
    
      int lm=1e5;//not Mx(A,B,C,D) for *2
      jc[0]=1;for(int i=1;i<=lm;i++)jc[i]=(ll)jc[i-1]*i%mod;
      jcn[lm]=pw(jc[lm],mod-2);
      for(int i=lm-1;i>=0;i--)jcn[i]=(ll)jcn[i+1]*(i+1)%mod;
    }
    int C2(int n,int m)
    {
      if(n==(-1)&&m==(-1))return 1;///
      if(n<0||m<0||n<m)return 0;
      return (ll)jc[n]*jcn[m]%mod*jcn[n-m]%mod;
    }
    int cal(int t,bool fx,int a,int b,int c,int d)
    {
      if(a<0||b<0||c<0||d<0)return 0;//
      if(!t) return ((!a)&&(!b)&&(!c)&&(!d));
      int t0,t1,c0,c1;
      if(!fx)c0=c+1,c1=b; else c0=c,c1=b+1;
      if(!fx)t0=a+c0-1,t1=d+c1; else t0=a+c0,t1=d+c1-1;
      int ret=0;
      if(t0+t1==t) ret=(ll)C2(t0-1,c0-1)*C2(t1-1,c1-1)%mod;
      c0=c; c1=b; t0=a+c0; t1=d+c1;
      if(t0+t1==t) ret=(ret+(ll)C2(t0-1,c0-1)*C2(t1-1,c1-1))%mod;
      return ret;
    }
    int dfs(int t,bool fx,int a,int b,int c,int d)
    {
      if(a<0||b<0||c<0||d<0)return 0;
      if(!t) return ((!a)&&(!b)&&(!c)&&(!d));
      int ta=a,tb=b,tc=c,td=d;
      if(s[t]=='0')
        {
          if(!fx)ta--; else tc--;
          int ret=dfs(t-1,0,ta,tb,tc,td);
          return ret;
        }
      if(!fx)ta--; else tc--;
      int ret=cal(t-1,0,ta,tb,tc,td);
      ta=a; tc=c; if(!fx)tb--; else td--;
      ret=upt(ret+dfs(t-1,1,ta,tb,tc,td));
      return ret;
    }
    int solve()
    {
      int ret=0;
      for(int t=1;t<n;t++)
        ret=upt(ret+cal(t-1,1,A,B,C,D));
      if(n)ret=upt(ret+dfs(n-1,1,A,B,C,D));//if
      return ret;
    }
    int main()
    {
      scanf("%s",s1+1); scanf("%s",s2+1);
      scanf("%d%d%d%d",&A,&B,&C,&D);
      if(B<C-1||B>C){puts("0");return 0;}///?
      n=strlen(s1+1); reverse(s1+1,s1+n+1);
      init(); int ans=upt(-solve());
      n=strlen(s2+1); reverse(s2+1,s2+n+1);
      memcpy(s,s2,sizeof s2); ans=upt(ans+solve());
      printf("%d
    ",ans);
      return 0;
    }
    View Code

     第三题:http://codeforces.com/contest/780/problem/H

      题意: 给出 n 个点的坐标,第 i 个点和第 i%n+1 个点连线组成一个环,有 m 个动点在环上移动,满足每个动点的速度相同、相邻动点距离相等。

         求一个最小的 R,满足存在一个时刻,任意相邻点的距离 <= R 。

      学习了 #52224787(by Idxoi) 的 AC 代码。

      考虑把 “第 i 个点和第 i%m+1 个点的距离” 随时间变化的函数图象画出来。如果两个点分别在两条线上,那么这个图象是一个二次函数。整个图象就是 O(n) 段二次函数接起来。

      考虑二分答案,那么图象中 y 在 mid 以下部分的 x 都是合法的;该 mid 合法满足存在一个 x ,使得 x , x+T/m , x+2*T/m , ... x+m*T/m 都是合法的( T 是总长度;即等距的 m 个位置都是合法的)。

      已知 mid ,对于一段二次函数,易求其在 y=mid 一下部分的 x ,且对于一个二次函数这样的 x 是0/1/2个区间;

      所以把整个图象分成各个二次函数,然后求出一些合法的 x 区间;再考虑把 T 分成 [ 0 , T/m ] , [ T/m , 2*T/m ] , ... , [ (m-1)*T/m , m*T/m ] ,然后把这 m 个区间里的 “合法 x 区间集合” 都叠起来,如果有一个位置被覆盖了 m 次,那么该 mid 合法。

      所以把整个图象分成若干段,满足每段是一个二次函数,且每段只在一个 [ 0 , T/m ] , ... , [ (m-1)*T/m , m*T/m ] 这样的区间里;然后对每段求一下合法的 x 区间,用差分的形式记录下来,按位置排序后扫一遍看看有没有被覆盖 m 次的位置即可。

      注意这个排序是以位置为第一关键字、+1/-1为第二关键字;且要先减后加!

      注意虽然算的是至多 n*4 段(n*2 个端点,每个区间被 m 的限制切一次,总数再 *2),但空间要再开大。不太知道原因……可能是精度使得多出了一些段?

      注意二分不要像平常一样写。 mid 是否合法只是影响二分方向,最终的答案不一定是一个合法的 mid ,而是最后二分到的位置。可能是因为精度才这样的?

      找函数图象的实现方法就是把给出的 n 条线段的长度、方向都预处理出来,然后两个指针卡着两个点 st , en 的位置,每次走到 “ 下一个 [ 0 , T/m ] 这样的段的末端 ”、“ st 所在线段的末端 ” 、 “ en 所在线段的末端 ” 中较近的一个。就是看看哪个长度短,然后 st 、en 就移动到 “当前位置 + 长度×所在线段方向” 的位置。

      已知两动点 st , en 的当前位置以及移动方向向量(就是所在线段的方向),如何求出距离的二次函数方程?

        考虑 ( st=(a_1+c_1*x , b_1+d_1*x ) , en=(a_2+c_2*x , b_2+d_2*x ) ) (即,( (a_1,b_1) ) 就是 st 的初始位置, ( (c_1,d_1) ) 是移动方向, x 是时间自变量)

        ( dis^2 = ( (a_1+c_1*x) - (a_2+c_2*x) )^2 + ( ( b_1+d_1*x ) - ( b_2+d_2*x ) )^2 )(就是平常的 ( dis^2=(x_1-x_2)^2+(y_1-y_2)^2 ))

        ( dis^2 = ( (c_1-c_2)^2+(d_1-d_2)^2 )x^2 + 2[ (a_1-a_2)(c_1-c_2) + (b_1-b_2)(d_1-d_2) ]x + (a_1-a_2)^2 + (b_1-b_2)^2 )

        所以可知关于 (dis^2) 的二次函数 ( y=a*x^2+b*x+c ) 的系数。要判断 dis<=mid 的部分,就是判断 (dis^2<=mid^2) 的部分。

      注意到二次函数的 a 是 >=0 的,所以可以少讨论一点。

      注意在求交点的时候判断正负就不要加 eps 了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define db long double
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    const int N=(3e4+5)*10; const db eps=1e-9;
    int dcmp(db x){return (x>-eps)-(x<eps);}
    db Sqr(db x){return x*x;}
    
    int n,m,tot,cnt; db len[N];
    struct Node{
      db x,y;
      Node(db x=0,db y=0):x(x),y(y) {}
      Node operator+ (const Node &b)const{return Node(x+b.x,y+b.y);}
      Node operator- (const Node &b)const{return Node(x-b.x,y-b.y);}
      Node operator* (const db &b)const{return Node(x*b,y*b);}
      Node operator/ (const db &b)const{return Node(x/b,y/b);}
      db mod(){ return Sqr(x)+Sqr(y);}
    }a[N],dir[N];
    db dot(Node u,Node v){return u.x*v.x+u.y*v.y;}
    struct Dt{
      db ql,qr,a,b,c;
      Dt(db l=0,db r=0,db a=0,db b=0,db c=0):ql(l),qr(r),a(a),b(b),c(c) {}
    }h[N];
    struct F{
      db p;int v;
      F(db p=0,int v=0):p(p),v(v) {}
      bool operator< (const F &b)const
      {return dcmp(p-b.p)==0?v<b.v:p<b.p;}//v<b.v not v>b.v
    }tp[N<<1];
    
    db chk(db mid)
    {
      cnt=0;
      for(int i=1;i<=tot;i++)
        {
          db a=h[i].a,b=h[i].b,c=h[i].c-mid;//a>=0
          db ql=h[i].ql,qr=h[i].qr;
          if(a<eps)
        {
          if(dcmp(b)==0)
            {
              if(c<eps)
            {tp[++cnt]=F(ql,1);tp[++cnt]=F(qr,-1);}
            }
          else
            {
              db x=-c/b;
              if(b>0&&x>0)
            {
              tp[++cnt]=F(ql,1);
              tp[++cnt]=F(min(ql+x,qr),-1);
            }
              else if(b<0&&ql+x<qr)
            {
              tp[++cnt]=F(ql+max(x,(db)0),1);
              tp[++cnt]=F(qr,-1);
            }
            }
        }
          else
        {
          db dlt=Sqr(b)-4*a*c; if(dlt<0)continue;
          dlt=sqrt(dlt); db tmp=2*a;
          db x0=ql+(-b-dlt)/tmp, x1=ql+(-b+dlt)/tmp;
          x0=max(x0,ql); x1=min(x1,qr);
          if(x0<x1)
            {
              tp[++cnt]=F(x0,1);tp[++cnt]=F(x1,-1);
            }
        }
        }
      sort(tp+1,tp+cnt+1);
      for(int i=1,lj=0;i<=cnt;i++)
        { lj+=tp[i].v; if(lj==m)return true;}
      return false;
    }
    void cz(int &x){ x++; if(x>n)x=1;}
    int main()
    {
      n=rdn();m=rdn();
      for(int i=1;i<=n;i++)a[i].x=rdn(),a[i].y=rdn();
      a[n+1]=a[1]; db sm=0;
      for(int i=1;i<=n;i++)
        {
          len[i]=sqrt((a[i+1]-a[i]).mod()); sm+=len[i];
          dir[i]=(a[i+1]-a[i])/len[i];
        }
      db ave=sm/m,L=len[1],R=ave,nw=0; int id=1;//nw=0 not ave
      int pl=1,pr=1;
      for(;dcmp(R-len[pr])>=0;pr++)R-=len[pr];
      Node st=a[1],en=a[pr]+dir[pr]*R; R=len[pr]-R;
      while(dcmp(sm-nw)>0)
        {
          db cr=min(id*ave-nw,min(L,R));
          Node d0=en-st,d1=dir[pr]-dir[pl];
          st=st+dir[pl]*cr; en=en+dir[pr]*cr;//after d0,d1
          h[++tot]=Dt(nw-(id-1)*ave,nw-(id-1)*ave+cr,
              d1.mod(),2*dot(d0,d1),d0.mod());
          L-=cr; if(dcmp(L)==0){cz(pl);st=a[pl];L=len[pl];}
          R-=cr; if(dcmp(R)==0){cz(pr);en=a[pr];R=len[pr];}
          //cz(pl) not ++pl
          nw+=cr; if(dcmp(id*ave-nw)==0)id++;//<= not ==
        }
      db l=0,r=ave;
      while(r-l>eps)
        {
          db mid=(l+r)/2;
          if(chk(Sqr(mid)))r=mid;
          else l=mid;
        }
      printf("%.10Lf
    ",l);//l not ans
      return 0;
    }
    View Code
  • 相关阅读:
    完了!生产事故!几百万消息在消息队列里积压了几个小时!
    crontab详解
    系统架构中为什么要引入消息中间件
    Linux常用命令
    什么是JWT(JSON WEB TOKEN)
    API接口安全性设计
    MySQLDump在使用之前一定要想到的事情
    api接口安全以及https
    shell study
    linux中注册系统服务—service命令的原理通俗
  • 原文地址:https://www.cnblogs.com/Narh/p/10965832.html
Copyright © 2020-2023  润新知