2020.5.16-ICPC Central Europe Regional Contest 2019

A. ABB

#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define ZERO (1e-10)
#define INF int(1e9+1)
#define CL(A,I) (memset(A,I,sizeof(A)))
#define DEB printf("DEB!\n");
#define D(X) cout<<"  "<<#X": "<<X<<endl;
#define EQ(A,B) (A+ZERO>B&&A-ZERO<B)
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
#define IN(n) int n;scanf("%d",&n);
#define FOR(i, m, n) for (int i(m); i < n; i++)
#define F(n) FOR(i,0,n)
#define FF(n) FOR(j,0,n)
#define FT(m, n) FOR(k, m, n)
#define aa first
#define bb second
void ga(int N,int *A){F(N)scanf("%d",A+i);}
#define MX (1<<20)
ll pw(ll n,ll k,ll MOD){
    ll r(1);
    while(k){
        if(k&1)r*=n,r%=MOD;
        n*=n,n%=MOD,k>>=1;
    }
    return r;
}
ll inv(ll a,ll MOD){return pw(a,MOD-2,MOD);}
struct HSH{
    int MOD,N,I[MX],F[MX],P;
    void ini(char*r,int M=1000000007,ll b=257){
        MOD=M,N=strlen(r),P=1,*I=1,I[1]=inv(b,MOD),*F=*r;
        FT(2,N)I[k]=I[k-1]*ll(I[1])%MOD;
        FT(1,N)P=P*b%MOD,F[k]=(ll(P)*r[k]+F[k-1])%MOD;
    }
    ll get(int b,int e){if(b>e)swap(b,e);return (F[e]-ll(b?F[b-1]:0)+MOD)*I[b]%MOD;}
}t,T,r,R;
char s[MX];
int N,X=INF;
bool isP(int b,int e){
    int H=(e-b+1)/2;
    if((e-b+1)&1)return t.get(b,b+H)==r.get(N-1-b-H,N-1-e)&&T.get(b,b+H)==R.get(N-1-b-H,N-1-e);
    return t.get(b,b+H-1)==r.get(N-1-b-H,N-1-e)&&T.get(b,b+H-1)==R.get(N-1-b-H,N-1-e);
}
int main(void){
    scanf("%d%s",&N,s);
    t.ini(s),T.ini(s,1e9+9,661);
    reverse(s,s+N),r.ini(s),R.ini(s,1e9+9,661);
    F(N)if(isP(i,N-1))return printf("%d\n",i),0;
    assert(0);
    return 0;
}

B. Be Geeks!

#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define ZERO (1e-10)
#define INF int(1e9+1)
#define CL(A,I) (memset(A,I,sizeof(A)))
#define DEB printf("DEB!\n");
#define D(X) cout<<"  "<<#X": "<<X<<endl;
#define EQ(A,B) (A+ZERO>B&&A-ZERO<B)
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
#define IN(n) int n;scanf("%d",&n);
#define FOR(i, m, n) for (int i(m); i < n; i++)
#define F(n) FOR(i,0,n)
#define FF(n) FOR(j,0,n)
#define FT(m, n) FOR(k, m, n)
#define aa first
#define bb second
void ga(int N,int *A){F(N)scanf("%d",A+i);}
#define LG (18)
#define MX (1<<LG)
#define P2(v) (!(v&(v-1)))
struct RMQx{
    int dp[MX][LG+2],G[MX],XX,O=-1;
    void ini(int*A,int n){
        if(!XX++)FT(1,MX)G[k]=O+=P2(k);
        F(n)dp[i][0]=i;
        FT(1,k-(1<<k)+n+1)F(n+1-(1<<k))
            if(A[dp[i][k-1]]>A[dp[i+(1<<(k-1))][k-1]])
                dp[i][k]=dp[i][k-1];
            else dp[i][k]=dp[i+(1<<(k-1))][k-1];      
    }
    int qy(int *A,int L,int R){
        int j(G[R-L+1]);
        if(A[dp[L][j]]>=A[dp[R-(1<<j)+1][j]])
            return dp[L][j];
        return dp[R-(1<<j)+1][j];
    }
}R;
struct RMQg{
    int dp[MX][LG+2],G[MX],XX,O=-1;
    void ini(int *A,int n){
        if(!XX++)FT(1,MX)G[k]=O+=P2(k);
        F(n)dp[i][0]=A[i];
        FT(1,k-(1<<k)+n+1)F(n+1-(1<<k))
            dp[i][k]=__gcd(dp[i][k-1],dp[i+(1<<(k-1))][k-1]);
    }
    int qy(int L,int R){
        int j(G[R-L+1]);
        return __gcd(dp[L][j],dp[R-(1<<j)+1][j]);
    }
}G;
#define MOD 1000000007
int N,A[MX],S,g,I,x,y;
bool OK(int t){
    if(t==y)return 1;
    return G.qy(I,t)<g;
}
bool ok(int t){
    if(t==x)return 1;
    return G.qy(t,I)<g;
}
int bs(int B,int E){
    int M;
    while(B+3<E)
        if(ok(M=(B+E)>>1))B=M;
        else E=M-1;
    while(!ok(E))--E;
    return E;
}
int BS(int B,int E){
    int M;
    while(B<E)
        if(OK(M=(B+E)>>1))E=M;
        else B=M+1;
    return E;
}
vi X,Y;
#define DF(B,E) (max(B,E)-min(B,E))
int go(int b,int e){
    if(b>e)return 0;
    x=b-1,y=e+1;
    I=R.qy(A,b,e);
    int S=0,J=I,F=I;
    X.clear(),Y.clear();
    X.PB(I-1),Y.PB(I+1);
    while(J<=e)g=G.qy(I,J),J=BS(J,e+1),X.PB(J-1);
    J=I;
    while(J>=b)g=G.qy(J,I),J=bs(b-1,J),Y.PB(J+1);
    FT(1,(int)X.size())FOR(i,1,(int)Y.size())
        S=(S+ll(A[I])*__gcd(G.qy(I,X[k]),G.qy(Y[i],I))%MOD*DF(X[k],X[k-1])%MOD*DF(Y[i],Y[i-1]))%MOD;
    return (ll(S)+go(b,F-1)+go(F+1,e))%MOD;
}
int main(void){
    scanf("%d",&N),ga(N,A),R.ini(A,N),G.ini(A,N);
    printf("%d\n",go(0,N-1));
    return 0;
}

C. Bob in Wonderland

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <vector>

using namespace std;

typedef long long int ll;
typedef pair<int, int> pii;

#define PB push_back
#define MP make_pair

#define FOR(prom, a, b) for(int prom = (a); prom < (b); prom++)
#define FORD(prom, a, b) for(int prom = (a); prom > (b); prom--)
#define FORDE(prom, a, b) for(int prom = (a); prom >= (b); prom--)
#define R1(a) do{scanf("%d", &(a));}while(0)
#define R2(a, b) do{scanf("%d%d", &(a), &(b));}while(0)
#define R3(a, b, c) do{scanf("%d%d%d", &(a), &(b), &(c));}while(0)
#define SV(vec) do{int s_v_;scanf("%d", &(s_v_));vec.PB(s_v_);}while(0)
#define MM(co, cim) memset((co), (cim), sizeof((co)))
#define DEB(x) cerr << ">>> " << #x << " : " << x << endl;
#define INF 1000000007

int n, from, to, res;
vector<int> g[300014];

int main ()
{
  R1(n);
  FOR(i, 0, n - 1)
  {
    R2(from, to);
    --from;
    --to;
    g[from].PB(to);
    g[to].PB(from);
  }
  res = 0;
  FOR(i, 0, n) res += max((int)g[i].size() - 2, 0);
  printf("%d\n", res);
  return 0;
}

D. Deep800080

#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef double ld;
typedef vector<ll> vi;
// push_back insert lower_bound upper_bound erase
#define F(a) for ( ll i = 0; i < (ll)(a); ++i )

#define EPS (1e-8)
bool eq(ld a, ld b) { return fabs(a-b) <= fabs(a+b) * EPS; }

struct Pt{
    ld x, y;
    ll flag;
    bool operator <(const Pt &p) const {
        return x < p.x-EPS || (eq(x, p.x) && y < p.y-EPS);
    }
    Pt operator+(const Pt &p){ return{x+p.x, y+p.y}; }
    Pt operator-(const Pt &p){ return{x-p.x, y-p.y}; }
    Pt operator-(){ return{-x, -y}; }
    Pt operator*(ld d){ return {x*d, y*d}; }
    Pt operator/(ld d){ return {x/d, y/d}; }
    friend ostream &operator<<(ostream &os, const Pt &a){ os<<a.x<<' '<<a.y; return os; }
    friend istream &operator>>(istream &is, Pt &a){ is>>a.x>>a.y; return is; }
};
struct Line {
    Pt a, b;
    bool operator<(Line &l){
        Pt v=b-a, w=l.b-l.a;
        return atan2(v.y, v.x) < atan2(w.y, w.x);
    }
};
struct Cir {
    Pt s;
    ld r;
    Pt point(double a)const{ return {s.x+cos(a)*r, s.y+sin(a)*r}; }  
    bool operator<(const Cir &a){ return r<a.r; }  
};
ld vec(Pt a, Pt b){ return a.x*b.y-a.y*b.x; }
ld vec(Pt a, Pt b, Pt c){ return vec(b-a, c-a); }
ld norm(Pt a){ return hypot(a.x, a.y); }
ld line_point_dist(Line l, Pt p){ return fabs(vec(p-l.a, l.b-l.a)/norm(l.b-l.a)); }
Pt scale_to(Pt a, ld res){ return a*res/norm(a); }
Pt normal(Pt a){ ld n=norm(a); return {-a.y/n, a.x/n}; }
Pt lines_intersection(Line p, Line q){
    Pt v=p.b-p.a;
    Pt w=q.b-q.a;
    ld t=vec(w, p.a-q.a)/vec(v, w);
    return p.a+v*t;
}
Pt line_point_closest_point(Line a, Pt b){
    return lines_intersection(a, {b, b+normal(a.b-a.a)});
}
ld circle_line_distance(Cir &a, Line &b){
    return max(line_point_dist(b, a.s)-a.r, 0.);
}
ll circle_line_intersection(Cir a, Line b, Pt &p1, Pt &p2){
    if(circle_line_distance(a, b)>0)return 0;
    Pt dv = line_point_closest_point(b, a.s);
    ld d = norm(dv-a.s);
    ld h = sqrt(a.r*a.r-d*d);
    Pt n = scale_to(b.b-b.a, h);
    p1 = dv+n;
    p2 = dv-n;
    return 1+!(eq(p1.x, p2.x) && eq(p1.y, p2.y)); // returns the number of intersections
}

ll solve(ll N, ld R, Line l, vector<Cir> a){
    for(Cir &p:a) p.r = R+0.00001;
    vector<Pt> p;
    F(N){
        Pt q, w;
        ll e = circle_line_intersection(a[i], l, q, w);
        if(e){
            q.flag = +1;
            w.flag = -1;
            p.push_back(q);
            p.push_back(w);
        }
    }
    sort(p.begin(), p.end());
    //for(Pt q:p)cerr<<q<<endl;
    ll mx=0,s=0;
    for(Pt q : p){
        s += q.flag;
        mx = max(mx, abs(s));
    }
    return mx;
}

int main(){
    ll N;
    ld R;
    Line l;
    l.a = {0, 0};
    cin >> N >> R >> l.b;
    vector<Cir> a(N);
    for(Cir &p:a) cin >> p.s;
    ll mx=solve(N, R, l, a);
    //ll mx2=solve(N, R+0.00101, l, a); // safe margin
    //assert(mx==mx2);
    cout<<mx<<endl;
    return 0;
}

E. Zeldain Garden

#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define ZERO (1e-10)
#define INF int(1e9+1)
#define CL(A,I) (memset(A,I,sizeof(A)))
#define DEB printf("DEB!\n");
#define D(X) cout<<"  "<<#X": "<<X<<endl;
#define EQ(A,B) (A+ZERO>B&&A-ZERO<B)
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
#define IN(n) int n;scanf("%d",&n);
#define FOR(i, m, n) for (int i(m); i < n; i++)
#define F(n) FOR(i,0,n)
#define FF(n) FOR(j,0,n)
#define FT(m, n) FOR(k, m, n)
#define aa first
#define bb second
void ga(int N,int *A){F(N)scanf("%d",A+i);}
ll X,N,Q,S;
ll go(ll N){
    if(!N)return 0;
    Q=sqrt(N+ZERO),S=0;
    for(ll i=1;i<=Q;++i)S+=N/i;
    return ll(S*__int128(2)-__int128(Q)*Q);
}
int main(void){
    scanf("%lld%lld",&X,&N);
    printf("%lld\n",go(N)-go(X-1));
    return 0;
}

F. Light Emitting Hindenburg

#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define ZERO (1e-10)
#define INF int(1e9+1)
#define CL(A,I) (memset(A,I,sizeof(A)))
#define DEB printf("DEB!\n");
#define D(X) cout<<"  "<<#X": "<<X<<endl;
#define EQ(A,B) (A+ZERO>B&&A-ZERO<B)
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
#define IN(n) int n;scanf("%d",&n);
#define FOR(i, m, n) for (int i(m); i < n; i++)
#define F(n) FOR(i,0,n)
#define FF(n) FOR(j,0,n)
#define FT(m, n) FOR(k, m, n)
#define aa first
#define bb second
void ga(int N,int *A){F(N)scanf("%d",A+i);}
vi A,B;
int N,K,a,o=~0;
int main(void){
    scanf("%d%d",&N,&K);
    F(N)scanf("%d",&a),A.PB(a);
    for(int i=1<<29;i;i>>=1){
        B.clear();
        for(int h:A)if(h&i)B.PB(h);
        if((int)B.size()>=K)A=B;
    }
    for(int h:A)o&=h;
    printf("%d\n",o);
    return 0;
}

G. K==S

#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define ZERO (1e-10)
#define INF int(1e9+1)
#define CL(A,I) (memset(A,I,sizeof(A)))
#define DEB printf("DEB!\n");
#define D(X) cout<<"  "<<#X": "<<X<<endl;
#define EQ(A,B) (A+ZERO>B&&A-ZERO<B)
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
#define IN(n) int n;scanf("%d",&n);
#define FOR(i, m, n) for (int i(m); i < n; i++)
#define F(n) FOR(i,0,n)
#define FF(n) FOR(j,0,n)
#define FT(m, n) FOR(k, m, n)
#define aa first
#define bb second
void ga(int N,int *A){F(N)scanf("%d",A+i);}
#define MX (106)
#define AL (26)
int g[MX][AL],f[MX],E,q[MX],O[MX];
void ini(){E=1;F(AL)g[0][i]=0;CL(f,0),CL(O,0);}
void add(char*s){
    int L=strlen(s),u=0,c;
    F(L){
        if(!g[u][c=s[i]-97]){
            g[u][c]=E++;
            F(AL)g[E-1][i]=0;
        }
        u=g[u][c];
    }
    O[u]=1;
}
void bld(){
    int x,r,b=-1,e=0,u;
    F(AL)if(g[0][i])f[g[0][i]]=0,q[e++]=g[0][i];
    while(++b<e)F(AL){
        x=g[u=q[b]][i],r=g[f[u]][i];
        if(!x)g[u][i]=r;
        else{
            q[e++]=x,f[x]=r;
            O[x]|=O[r];
        }
    }
}
#define MM (MX)
void mul(int A[MM][MM],int B[MM][MM],int R[MM][MM],int W,int M){
    F(W)FF(W)R[i][j]=0;
    F(W)FF(W){
        ll D=M*1ll*M,S=0;;
        FT(0,W)if((S+=A[i][k]*1ll*B[k][j])>=D)S-=D;
        R[i][j]=S%M;
    }
}
void pw(int M[MM][MM],int R[MM][MM],int W,ll k,int MD){
    static int E[MM][MM],H[MM][MM];
    F(W)FF(W)R[i][j]=E[i][j]=i==j;
    while(k){
        if(k&1)mul(E,M,R,W,MD),memcpy(E,R,sizeof(E));
        mul(M,M,H,W,MD);
        memcpy(M,H,sizeof(H));
        k>>=1;
    }
}
#define MOD 1000000007
ll pw(ll n,ll k){
    ll r(1);
    while(k){
        if(k&1)r*=n,r%=MOD;
        n*=n,n%=MOD;
        k>>=1;
    }
    return r;
}
char s[MX];
int L,N,Q,M[MX][MX],R[MX][MX];
int main(void){
    scanf("%d%d",&N,&Q),ini();
    F(Q){
        scanf("%*d%s",s);
        add(s);
    }
    bld();
    F(E)FF(26)if(O[g[i][j]])++M[i][E];
              else ++M[i][g[i][j]];
    M[E][E]=26;
    pw(M,R,E+1,N,MOD);
    printf("%lld\n",(pw(26,N)-R[0][E]+MOD)%MOD);
    return 0;
}

 H. Ponk Warshall

/**
 * CTU Open 2019
 * Problem Solution: DNA Swaps
 */

#include <cassert>
#include <iostream>
#include <vector>
#include <set>
#include <map>

using namespace std;

int main(void)
{
  map<char, int> letterid {{'A', 0}, {'C', 1}, {'G', 2}, {'T', 3}};
  string dna1, dna2;
  while (cin >> dna1 >> dna2)
  { 
    int len = dna1.length();
    vector<vector<int>> ecnt(4, vector<int>(4));
    for (int i = 0; i < len; ++i) {
      int l1 = letterid[dna1[i]];
      int l2 = letterid[dna2[i]];
      ++ecnt[l1][l2];
    }
    int result = 0;
    for (int i = 0; i < 4; ++i)
      for (int j = 0; j < 4; ++j)
        if(i != j && ecnt[i][j] >= ecnt[j][i]) {
          result += ecnt[j][i];
          ecnt[i][j] -= ecnt[j][i];
          ecnt[j][i] = 0;
        }
    for (int i = 0; i < 4; ++i)
      for (int j = 0; j < 4; ++j)
        for (int k = 0; k < 4; ++k) {
          if(i == j || i == k || j == k)
            continue;
          int min = std::min(std::min(ecnt[i][j], ecnt[j][k]), ecnt[k][i]);
          result += 2 * min;
          ecnt[i][j] -= min;
          ecnt[j][k] -= min;
          ecnt[k][i] -= min;
        }
    int rest = 0;
    for (int i = 0; i < 4; ++i)
      for (int j = 0; j < 4; ++j)
        if(i != j)
          rest += ecnt[i][j];
    result += 3 * rest / 4;
    cout << result << endl;
  }
  return 0;
}

 I. Saba1000kg

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <vector>

using namespace std;

typedef long long int ll;
typedef pair<int, int> pii;

#define PB push_back
#define MP make_pair

#define FOR(prom, a, b) for(int prom = (a); prom < (b); prom++)
#define FORD(prom, a, b) for(int prom = (a); prom > (b); prom--)
#define FORDE(prom, a, b) for(int prom = (a); prom >= (b); prom--)
#define R1(a) do{scanf("%d", &(a));}while(0)
#define R2(a, b) do{scanf("%d%d", &(a), &(b));}while(0)
#define R3(a, b, c) do{scanf("%d%d%d", &(a), &(b), &(c));}while(0)
#define SV(vec) do{int s_v_;scanf("%d", &(s_v_));vec.PB(s_v_);}while(0)
#define MM(co, cim) memset((co), (cim), sizeof((co)))
#define DEB(x) cerr << ">>> " << #x << " : " << x << endl;
#define INF 1000000007

int n, m, q, from, to, sqn, qs, x, u[100014], cc;
vector<int> g[100014], qvec, ng[100014];
set<pii> edg;
set<int> qset;

pair<int, int> ge (int from, int to)
{
  return MP(min(from, to), max(from, to));
}

void go (int x)
{
  if (u[x]) return;
  u[x] = 1;
  FOR(i, 0, (int)ng[x].size()) go(ng[x][i]);
}

int main ()
{
  R3(n, m, q);
  FOR(i, 0, m)
  {
    R2(from, to);
    g[from].PB(to);
    g[to].PB(from);
    edg.insert(ge(from, to));
  }
  sqn = 1;
  while (sqn * sqn < n) ++sqn;
  FOR(qn, 0, q)
  {
    qvec.clear();
    qset.clear();
    R1(qs);
    FOR(i, 0, qs)
    {
      R1(x);
      qvec.PB(x);
      qset.insert(x);
      ng[x].clear();
      u[x] = 0;
    }
    if (qs <= sqn)
    {
      FOR(i, 0, qs) FOR(j, i + 1, qs) 
      {
        from = qvec[i];
        to = qvec[j];
        if (edg.count(ge(from, to)))
        {
          ng[from].PB(to);
          ng[to].PB(from);
        }
      }
    }
    else
    {
      FOR(i, 0, qs) FOR(j, 0, (int)g[qvec[i]].size())
      {
        from = qvec[i];
        to = g[from][j];
        if (qset.count(to))
        {
          ng[from].PB(to);
          ng[to].PB(from);
        }
      }
    }
    cc = 0;
    FOR(i, 0, qs) if (!u[qvec[i]])
    {
      go(qvec[i]);
      ++cc;
    }
    printf("%d\n", cc);
  }
  
  return 0;
}

 J. Screamers in the Storm

#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef double ld;
typedef vector<ll> vi;
// push_back insert lower_bound upper_bound erase

#define F(a) for ( ll i = 0; i < (ll)(a); ++i )

// 1e-12 is too low
#define EPS (1e-10)
//bool eq(ld a, ld b) { return fabs(a-b) <= fabs(a+b) * EPS; } // cannot compare very small numbers to each other
bool eq(ld a, ld b) { return abs(a-b) <= EPS; }
int dcmp(ld x){ return (fabs(x)<EPS) ? 0 : (x<0 ? -1 : 1); }

struct Pt{
    ld x, y;
    bool operator <(const Pt &p) const {
        return x < p.x-EPS || (eq(x, p.x) && y < p.y-EPS);
    }
    Pt operator+(const Pt &p){ return{x+p.x, y+p.y}; }
    Pt operator-(const Pt &p){ return{x-p.x, y-p.y}; }
    Pt operator-(){ return{-x, -y}; }
    Pt operator*(ld d){ return {x*d, y*d}; }
    Pt operator/(ld d){ return {x/d, y/d}; }
    friend ostream &operator<<(ostream &os, const Pt &a){ os<<a.x<<' '<<a.y; return os; }
    friend istream &operator>>(istream &is, Pt &a){ is>>a.x>>a.y; return is; }
};
struct Line {
    Pt a, b;
    ll side; // 0=east-west, 1=north-south, 2=outside the roof
    bool operator<(Line &l){
        Pt v=b-a, w=l.b-l.a;
        return atan2(v.y, v.x) < atan2(w.y, w.x);
    }
    friend ostream &operator<<(ostream &os, const Line &l){ os<<l.a<<' '<<l.b; return os; }
};
ld vec(Pt a, Pt b){ return a.x*b.y-a.y*b.x; }
ld vec(Pt a, Pt b, Pt c){ return vec(b-a, c-a); }
ld dot(Pt a, Pt b){ return a.x*b.x+a.y*b.y; }
ld norm(Pt a){ return hypot(a.x, a.y); }
ld line_point_dist(Line l, Pt p){ return fabs(vec(p-l.a, l.b-l.a)/norm(l.b-l.a)); }
Pt scale_to(Pt a, ld res){ return a*res/norm(a); }
Pt normal(Pt a){ ld n=norm(a); return {-a.y/n, a.x/n}; }
ld points_distance(Pt a, Pt b){ return norm(b-a); }
ld angle2(Pt a, Pt b){
    a=scale_to(a, 1);
    b=scale_to(b, 1);
    ld ang=acos(dot(a, b));
    //ld ang=acos(dot(a, b)/norm(a)/norm(b));
    if(ang>M_PI)ang-=2*M_PI;
    return ang;
}
ld angle(Pt a, Pt b){
    ld ang=atan2(vec(a,b),dot(a,b));
    if(ang>M_PI)ang-=2*M_PI;
    if(ang<-M_PI)ang+=2*M_PI;
    return ang;
}
Pt old_lines_intersection(Line p, Line q){
    Pt v=p.b-p.a;
    Pt w=q.b-q.a;
    ld t=vec(w, p.a-q.a)/vec(v, w);
    return p.a+v*t;
}
Pt lines_intersection(Line p, Line q){
    Pt v=p.b-p.a;
    Pt w=q.b-q.a;
    ld t=vec(w, p.a-q.a)/vec(v, w);
    Pt res=p.a+v*t;
    //assert(fabs((ld)0 - vec(p.a,p.b,res))<1e-2);
    //assert(fabs((ld)0 - vec(q.a,q.b,res))<1e-2);
    return res;
}
Pt line_point_closest_point(Line a, Pt b){
    return lines_intersection(a, {b, b+normal(a.b-a.a)});
}
bool is_point_on_segment(Pt p, Line s){
    return dcmp(vec(s.a-p, s.b-p))==0 && dcmp(dot(s.a-p, s.b-p))<=0;
}
bool is_point_in_polygon_clock(Pt p, vector<Line> &lines){
    for(Line &l:lines)if(is_point_on_segment(p, l))return true;
    ld sum = 0;
    for(Line &l:lines){
        ld ang=angle(l.a-p, l.b-p);
        //cerr<<"angle: "<<ang<<endl;
        sum += ang;
    }
    //cerr<<"sum: "<<sum<<", eq to 0: "<<eq(sum,0)<<endl;
    return !eq(sum, 0);
}

int is_point_in_polygon(Pt p, vector<Line> &lines){
    ll n=lines.size(), wn=0;
    for(int i=0; i<n; ++i){
        Pt &p1 = lines[i].a;
        Pt &p2 = lines[i].b;
        if(is_point_on_segment(p, lines[i])) return 1;//point on the border
        int k = dcmp(vec(p2-p1, p-p1));
        int d1 = dcmp(p1.y-p.y);
        int d2 = dcmp(p2.y-p.y);
        if(k>0 && d1<=0 && d2>0) wn++;
        if(k<0 && d2<=0 && d1>0) wn--;
    }
    return wn;// wn=1 point is inside, 0 outisde
}
bool point_is_inside2(Pt p, vector<Line> &poly){
    for(Line &l:poly)if(is_point_on_segment(p, l))return true;
    ll r=0;
    p.x += EPS/2;
    p.y += EPS/2;
    for(int i=0; i<4; ++i){
        ll cnt = 0;
        for(Line &l:poly){
            if(p.y < l.a.y)
                if(l.a.x < p.x+EPS && p.x < l.b.x || l.b.x < p.x+EPS && p.x < l.a.x)
                    cnt+=1;
        }
        if((cnt%2) == 0) r++;
        swap(p.x,p.y);
        p.y=-p.y;
    }
    return r<4;
}
bool point_is_inside(Pt p, vector<Line> &poly){
    vector<bool> res;
    //res.push_back(point_is_inside2(p, poly));
    //res.push_back(is_point_in_polygon(p, poly));
    res.push_back(is_point_in_polygon_clock(p, poly));
    assert(res.size());
    //cerr<<"inside?: "; F(res.size())cerr<<res[i]<<' '; cerr<<endl;
    F(res.size()-1){
        if(res[i]!=res[i+1]){
            cerr<<"point is inside results: "; for(ll n:res)cerr<<n<<' '; cerr<<endl;
            cerr<<"and polygon:";for(Line l:poly)cerr<<" ["<<l.a<<"]"; cerr<<endl;
            cerr<<fixed<<setprecision(12);
            cerr<<"for point ["<<p<<"]\n";
            cerr<<endl;
            //cerr<<is_point_in_polygon_clock(p, poly)<<endl;
            assert(res[i]==res[i+1]);
        }
    }
    return res[0];
}


ll N, M;
Line l;
ld line_length, line_ang;
vector<Pt> a;
vector<Line> lines;
void load(){
    cin>>N;
    cin>>l.a>>l.b;
    Pt d=l.b-l.a;
    a.assign(N, {});
    F(N) cin>>a[i];
    lines.assign(N, {});
    F(N) lines[i]={a[i], a[(i+1)%N]};
    F(N) lines[i].side=eq(lines[i].a.y,lines[i].b.y);
}

Pt point_from_ratio(ld ratio){
    return l.a*(1-ratio)+l.b*ratio;
}

pair<ll,ld> find_closest_side(ld ratio){
    if(!(ratio>-2*EPS && ratio<1+2*EPS)){
        cerr<<"ratio: "<<ratio<<endl;
        assert(false);
    }
    Pt center = point_from_ratio(ratio);
    ld dist=1e62;
    ll id=-1;
    bool inside = point_is_inside(center, lines);
    F(N){
        Pt d1=center-lines[i].a;
        Pt d2=center-lines[i].b;
        ld d=dist;
        if(!inside || vec(lines[i].a, lines[i].b, center)>=-EPS){
            if(d1.x==d2.x && (d1.y*d2.y<0 || min(abs(d1.y),abs(d2.y)) <= abs(d1.x))) { d=min(d, abs(d1.x)); }
            if(d1.y==d2.y && (d1.x*d2.x<0 || min(abs(d1.x),abs(d2.x)) <= abs(d1.y))) { d=min(d, abs(d1.y)); }
        }
        //cerr<<"point "<<center<<" is "<<d<<" close to "<<i<<endl;
        if(d<dist-EPS){ // strictly prefer the first found
            dist=d;
            id=i;
        }
    }
    assert(id!=-1);
    //if(ratio<0.1){
        //cerr<<"closest to "<<id<<"  --  ["<<center<<"] in:"<<inside<<' '<<", dist: "<<dist<<endl;
    //}
    //cerr<<"closest side to "<<center<<" is "<<id<<endl;
    return {inside?id:(-1-id), dist};
}

struct Res{
    ld ratio;
    ll eid, state;
    Pt point;

    Res(ld ratio, ll eid):ratio(ratio),eid(eid){
        point = point_from_ratio(ratio+EPS);
        eid=find_closest_side(ratio).first;
        state = (eid<0) ? 2 : lines[eid].side; // outside is 2
    }
};
bool segment_intersect(Line s, Line t){
    ld c1=vec(s.b-s.a, t.a-s.a), c2=vec(s.b-s.a, t.b-s.a);
    ld c3=vec(t.b-t.a, s.a-t.a), c4=vec(t.b-t.a, s.b-t.a);
    return dcmp(c1)*dcmp(c2)<EPS && dcmp(c3)*dcmp(c4)<EPS;
}
bool line_line_equal_dir(Line a, Line b){
    return eq(0,vec(a.b-a.a, b.b-b.a));
}
pair<ld,ll> bsearch(ld low, ld high, ll low_edge_id){
    ld mid;
    //cerr<<setprecision(16);
    const ld max_step=0.5;
    while(low < high-EPS){
        mid = (low+high)/2;
        ld step_size = line_length*(mid-low);
        if(step_size > max_step){ // the biggest allowed step
            mid = low+max_step/line_length;
        }
        //cerr<<line_length<<' '<<low<<' '<<mid<<' '<<high<<endl;
        ll closest_eid = find_closest_side(mid).first;
        //cerr<<"FIND: "<<mid<<" -> "<<closest_eid<<" vs "<<low_edge_id<<" : "<<(closest_eid!=low_edge_id)<<endl;
        if(closest_eid != low_edge_id) high = mid;
        else low = mid+EPS;
    }
    return {high, find_closest_side(high).first};
}

int main(){
    load();
    Pt ldif=l.b-l.a;
    line_length=hypot(ldif.x, ldif.y);
    line_ang=atan2(ldif.y, ldif.x);
    ll first=find_closest_side(0.0).first;
    ll last=find_closest_side(1.0).first;
    if(first<0){ cerr<<"FIRST: "<<first<<endl; }
    assert(first>=0);
    if(last<0){ cerr<<"LAST: "<<last<<endl; }
    assert(last>=0);
    vector<Res> path;
    path.push_back({0.0, first});
    ll current_eid=first;
    ld current_ratio=0.0;
    //cout<<"0\n";return 0;
    
    // build all interesting points
    vector<Pt> crosses;
    // which cross with outer lines
    for(Line a:lines){
        if(segment_intersect(l, a)){
            Pt cross_point = lines_intersection(l, a);
            crosses.push_back(cross_point);
        }
    }
    // or lie at possible roof angle
    for(int i=0; i<lines.size(); ++i){ // even == horiz/vert
        Line q=lines[i];
        Pt qd=q.b-q.a;
        //ll sq=qd.x+qd.y;
        if(eq(qd.x,0))continue;
        for(int j=0; j<lines.size(); ++j){ // odd  == vert/horiz
            Line w=lines[j];
            Pt wd=w.b-w.a;
            if(eq(wd.y,0))continue;
            //ll sw=wd.x+wd.y;
            //ld dir=sw*sq>0 ? -1. : 1.;
            Pt origin = lines_intersection(q, w);
            //cerr<<"o: "<<origin<<", "<<q.a<<' '<<q.b<<' '<<w.a<<' '<<w.b<<endl;
            Line ne={origin, origin+Pt{1, 1}};
            Line nr={origin, origin+Pt{1, -1}};
            if(!line_line_equal_dir(ne, l)){
                Pt cross_point = lines_intersection(ne, l);
                crosses.push_back(cross_point);
            }
            if(!line_line_equal_dir(nr, l)){
                Pt cross_point = lines_intersection(nr, l);
                crosses.push_back(cross_point);
            }
        }
    }

    vector<ld> interesting_ratios;
    interesting_ratios.push_back(0.);
    interesting_ratios.push_back(1.);
    ld prev_ratio=-1;
    for(Pt cross:crosses){
        ld dist=points_distance(l.a, cross);
        //cerr<<cross<<' '<<dist<<endl;
        //ld mn_ratio=(dist-1e-2) / line_length;
        //ld mx_ratio=(dist+1e-2) / line_length;
        ld ratio=dist / line_length + 3*EPS;
        if((abs(ratio-prev_ratio)>EPS/2) && ratio>=-EPS && ratio < 1+EPS){
            interesting_ratios.push_back(ratio);
            prev_ratio=ratio;
        }
    }
    sort(interesting_ratios.begin(), interesting_ratios.end());


    for(ld new_ratio : interesting_ratios){
        ll new_eid = find_closest_side(new_ratio).first;
        path.push_back({new_ratio, new_eid});
    }
    path.push_back({1.0, last});
    ld side_sum[3]; side_sum[0]=side_sum[1]=side_sum[2]=0; // north-south, east-west, outside
    ll last_side=-2;
    F(path.size()-1){
        ld dif=path[i+1].ratio-path[i].ratio;
        if(dif>EPS){
            ld eid=path[i].eid;
            ld ratio=path[i].ratio;
            //Pt center=l.a*(1-ratio)+l.b*ratio;
            ll side=path[i].state;
            assert(side >= 0 && side <= 2);
            side_sum[side]+=dif;
            //if(last_side != side){
                //cerr<<fixed<<setprecision(12);
                //cerr<<"add ref  "<<ratio<<" to "<<side<<endl;
                //last_side = side;
            //}
        }
    }
    ld sum=side_sum[0]*(hypot(1, abs(cos(line_ang))))+side_sum[1]*(hypot(1, abs(sin(line_ang))))+side_sum[2];
    ld res=sum*hypot(ldif.x, ldif.y);
    cout<<fixed<<setprecision(12);
    cout<<res<<endl;

    //cerr<<"sol: \n";F(3){ cerr<<"sum: "<<i<<": "<<side_sum[i]<<endl; }
    //ld sm=0;F(3)sm+=side_sum[i]; cerr<<"sumsum: "<<sm<<endl;

    //for(ld r:interesting_ratios){ cerr<<r<<' '; } cerr<<endl;
    // only for drawing testcases visual correctness check:
    //cout<<fixed<<setprecision(6);
    //for(auto p:path){
        //auto pr=find_closest_side(p.ratio);
        ////ll id = pr.first;
        //ld dist = pr.second;
        //cout<<p.point<<' '<<max((ld)0.1,dist)<<' '<<(p.state!=2 ? p.state : -1)<<endl;
    //}
    return 0;
}

K. The Bugs

#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define ZERO (1e-10)
#define INF int(1e9+1)
#define CL(A,I) (memset(A,I,sizeof(A)))
#define DEB printf("DEB!\n");
#define D(X) cout<<"  "<<#X": "<<X<<endl;
#define EQ(A,B) (A+ZERO>B&&A-ZERO<B)
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
#define IN(n) int n;scanf("%d",&n);
#define FOR(i, m, n) for (int i(m); i < n; i++)
#define F(n) FOR(i,0,n)
#define FF(n) FOR(j,0,n)
#define FT(m, n) FOR(k, m, n)
#define aa first
#define bb second
void ga(int N,int *A){F(N)scanf("%d",A+i);}
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
struct TP{
    typedef int tp;
    tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> T;
    void add(tp a){T.insert(a);} 
    void del(tp a){T.erase(a);}
    int cnt(tp a){return T.order_of_key(a);}
    tp kth(int a){return *T.find_by_order(a);}
    int gt(tp b,tp e){return cnt(e+1)-cnt(b);}
    int sz(){return T.size();}
    void clr(){T.clear();}
    int mn(){return kth(0);}
    int mx(){return kth(sz()-1);}
}T;
#define LG (18)
#define MX (1<<LG)
#define P2(v) (!(v&(v-1)))
struct RMQ{
    int dp[LG+2][MX],XX,O=-1,G[MX];
    void ini(int*A,int n){
        if(!XX++)FT(1,MX)G[k]=O+=P2(k);
        F(n)dp[0][i]=i;
        FT(1,k-(1<<k)+n+1)F(n+1-(1<<k))
            if(A[dp[k-1][i]]<A[dp[k-1][i+(1<<(k-1))]])
                dp[k][i]=dp[k-1][i];
            else dp[k][i]=dp[k-1][i+(1<<(k-1))];
    }
    int qy(int*A,int L,int R){
        const int j=G[R-L+1];
        if(A[dp[j][L]]<=A[dp[j][R-(1<<j)+1]])
            return A[dp[j][L]];
        return A[dp[j][R-(1<<j)+1]];
    }
}b;
struct RMQ2{
    int dp[MX][LG+2],G[MX],XX,O=-1;
    void ini(int*A,int n){
        if(!XX++)FT(1,MX)G[k]=O+=P2(k);
        F(n)dp[i][0]=i;
        FT(1,k-(1<<k)+n+1)F(n+1-(1<<k))
            if(A[dp[i][k-1]]>A[dp[i+(1<<(k-1))][k-1]])
                dp[i][k]=dp[i][k-1];
            else dp[i][k]=dp[i+(1<<(k-1))][k-1];      
    }
    int qy(int *A,int L,int R){
        int j(G[R-L+1]);
        if(A[dp[L][j]]>=A[dp[R-(1<<j)+1][j]])
            return A[dp[L][j]];
        return A[dp[R-(1<<j)+1][j]];
    }
}e;
int N,A[MX],X[MX][5],Y[MX][5];
int nrm(int a,int b,int c){
    int B[3]={a,b,c},L;
    sort(B,B+3),L=unique(B,B+3)-B;
    unordered_map<int,int> T;
    F(L)T[B[i]]=i+1;
    return 100*T[a]+10*T[b]+T[c];
}
void go(int X[MX][5]){
    T.clr();
    FT(1,N){
        T.add(A[k-1]);
        if(T.mn()<A[k])X[k][0]=T.mn();
        if(T.mx()>A[k])X[k][4]=T.mx();
        int I=T.cnt(A[k]);
        if(T.mx()>=A[k]&&T.kth(I)==A[k])X[k][2]=A[k];
        if(T.mn()<A[k])X[k][1]=T.kth(I-1);
        if(T.mx()>A[k])X[k][3]=~X[k][2]?T.kth(I+1):T.kth(I);
    }
}
set<int> O;
map<int,int> L;
int main(void){
    scanf("%d",&N),ga(N,A),CL(X,-1),CL(Y,-1),b.ini(A,N),e.ini(A,N);
    F(N){
        if(L.count(A[i])){
            if(b.qy(A,L[A[i]],i)<A[i])O.insert(212);
            if(e.qy(A,L[A[i]],i)>A[i])O.insert(121);
        }
        L[A[i]]=i;
    }
    go(X);
    reverse(A,A+N),go(Y);
    reverse(A,A+N);
    F(N/2)FF(5)swap(Y[i][j],Y[N-i-1][j]);
//    F(N){
//        DEB
//        printf("%d: ",A[i]);FF(5)printf(" %d",X[i][j]);puts("");
//        printf("%d: ",A[i]);FF(5)printf(" %d",Y[i][j]);puts("");
//    }
    F(N)FF(5)if(~X[i][j])FT(0,5)if(~Y[i][k])O.insert(nrm(X[i][j],A[i],Y[i][k]));
    for(auto&h:O)printf("%d\n",h);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/mxw000120/p/12952489.html