Problem:
Problem M: Manhattan Bomb
Problem
2次元平面上に$n$個の爆弾がある。爆弾にはそれぞれ1から$n$までの番号が割り振られており、$i$番目の爆弾は座標$(x_i,y_i)$に存在している。
なお、どの爆弾も原点からのマンハッタン距離が等しいことが分かっている。
$i$番目の爆弾が爆発したとき、座標$(x_i,y_i)$からのマンハッタン距離が$r_i$以内の座標に存在している爆弾も連鎖的に爆発する。
$n$個の爆弾それぞれについて、その爆弾のみに着火した場合に、爆発せずに残る爆弾の個数を求めよ。
Input
$n$
$x_1$ $y_1$ $r_1$
$x_2$ $y_2$ $r_2$
...
$x_n$ $y_n$ $r_n$
入力はすべて整数で与えられる。
1行目に爆弾の個数$n$が与えられる。
続く$n$行のうち$i$行目には$i$番目の爆弾の情報を表す$x_i,y_i,r_i$が空白区切りで与えられる。
Constraints
入力は以下の条件を満たす。
$2$ ≤ $n$ ≤ $2 \times 10^5$
$-10^9$ ≤ $x_i,y_i$ ≤ $10^9$
$1$ ≤ $r_i$ ≤ $10^9$
$|x_i|+|y_i| = |x_j|+|y_j|$  $( 1 ≤ i , j ≤ n )$
同じ座標に複数の爆弾が存在することはない
Output
$i$行目には$i$番目の爆弾のみに着火した場合に、爆発せずに残る爆弾の個数を出力せよ。
Sample Input 1
2
-1 -1 10
1 1 1
Sample Output 1
0
1
Sample Input 2
3
3 2 2
4 -1 4
1 -4 7
Sample Output 2
2
1
0

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;

template <typename T,typename E>
struct SegmentTree{
  using F = function<T(T,T)>;
  using G = function<T(T,E)>;
  Int n;
  F f;
  G g;
  T ti;
  vector<T> dat;
  SegmentTree(){};
  SegmentTree(Int n_,F f,G g,T ti):
    f(f),g(g),ti(ti){
    init(n_);
  }
  void init(Int n_){
    n=1;
    while(n<n_) n*=2;
    dat.assign(2*n-1,ti);
  }
  void build(Int n_, vector<T> v){
    for(Int i=0;i<n_;i++) dat[i+n-1]=v[i];
    for(Int i=n-2;i>=0;i--)
      dat[i]=f(dat[i*2+1],dat[i*2+2]);
  }
  void update(Int k,E a){
    k+=n-1;
    dat[k]=g(dat[k],a);
    while(k>0){
      k=(k-1)/2;
      dat[k]=f(dat[k*2+1],dat[k*2+2]);
    }
  }
  inline T query(Int a,Int b){
    T vl=ti,vr=ti;
    for(Int l=a+n,r=b+n;l<r;l>>=1,r>>=1) {
      if(l&1) vl=f(vl,dat[(l++)-1]);
      if(r&1) vr=f(dat[(--r)-1],vr);
    }
    return f(vl,vr);
  }
};

//INSERT ABOVE HERE
signed main(){
  Int n;
  cin>>n;
  using T = tuple<Int, Int, Int>;
  vector<T> v(n);
  map<T, Int> m;
  for(Int i=0;i<n;i++){
    Int x,y,r;
    cin>>x>>y>>r;
    v[i]=T(x+y,x-y,r);
    m[v[i]]=i;
  }
  
  sort(v.begin(),v.end(),[&](T a,T b){
      Int au,av,ar;
      tie(au,av,ar)=a;
      Int bu,bv,br;
      tie(bu,bv,br)=b;
      return atan2(av,au)<atan2(bv,bu);
    });

  for(Int i=0;i<n;i++) v.emplace_back(T(v[i]));
  for(Int i=0;i<n;i++) v.emplace_back(T(v[i]));

  using P = pair<Int, Int>;
  SegmentTree<P, P>::F f=[&](P a,P b){
    return P(min(a.first,b.first),max(a.second,b.second));};

  Int N=n*3;
  SegmentTree<P, P> seg(N,f,f,P(N,-1));
  for(Int i=0;i<N;i++) seg.update(i,P(i,i));

  auto check=[&](Int a,Int b){
    return max(abs(get<0>(v[a])-get<0>(v[b])),
	       abs(get<1>(v[a])-get<1>(v[b])))<=(get<2>(v[b]));
  };
  
  vector<Int> dp(N,N);
  for(Int i=0;i<N;i++){
    dp[i]=i;
    while(0<dp[i]&&check(dp[i]-1,i)) dp[i]=dp[dp[i]-1];
    seg.update(i,P(dp[i],dp[i]));
  }
  fill(dp.begin(),dp.end(),-1);
  for(Int i=N-1;i>=0;i--){
    dp[i]=i;
    while(dp[i]+1<N&&check(dp[i]+1,i)) dp[i]=dp[dp[i]+1];
    seg.update(i,P(dp[i],dp[i]));
  }
  
  Int flg=1;
  while(flg){
    flg=0;
    for(Int i=0;i<N;i++){
      auto a=seg.query(i,i+1);
      auto b=seg.query(a.first,a.second+1);
      flg|=(a!=b);
      seg.update(i,b);
    }
  }

  vector<Int> ans(n);
  for(Int i=0;i<n;i++){
    Int idx=m[v[i]];
    auto a=seg.query(n+i,n+i+1);
    Int k=(i-a.first+1)+(a.second-i+1)-1;
    ans[idx]=min(k,n);
  }
  
  for(Int i=0;i<n;i++) cout<<n-ans[i]<<endl;
  return 0;
}
accuracy: 1
time_ms: 1120
memory_kb: 71832
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define int long long

#define rep(i,n) for(int i=0;i<(n);i++)
#define pb push_back
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;

template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}



int L;

inline int T(pint p){
    if(p.fi==L)return 0;
    if(p.fi==-L)return 2;
    if(p.se==L)return 1;
    return 3;
}

bool comp(const pint &a,const pint &b){
    if(T(a)!=T(b))return T(a)<T(b);
    if(T(a)==0){
        return a.se<b.se;
    }
    else if(T(a)==1){
        return a.fi<b.fi;
    }
    else if(T(a)==2){
        return a.se>b.se;
    }
    else{
        return a.fi>b.fi;
    }
}

int dist(pint p,pint q){
    return max(abs(p.fi-q.fi),abs(p.se-q.se));
}


vpint ps;

int N;
int X[222222],Y[222222],R[222222];
int l[222222],r[222222];

int id(int k){
    int lb=-1,ub=N;
    while(ub-lb>1){
        int mid=(ub+lb)/2;
        if(comp(ps[mid],pint(Y[k],X[k])))lb=mid;
        else ub=mid;
    }
    return ub;
}

const int SEG=1<<18;
vector<vint>G(SEG*2);
void addEdge(int a,int b,int x,int k=0,int l=0,int r=SEG){
    if(r<=a||b<=l)return;
    if(a<=l&&r<=b){
        G[x].pb(k);
        return;
    }
    addEdge(a,b,x,k*2+1,l,(l+r)/2);
    addEdge(a,b,x,k*2+2,(l+r)/2,r);
}


namespace SCC{
    void visit(const vector<vector<int>>&G,vector<int>&vs,vector<int>&used,int v){
        used[v]=true;
        for(auto u:G[v]){
            if(!used[u])visit(G,vs,used,u);
        }
        vs.push_back(v);
    }

    void visit2(const vector<vector<int>>&T,vector<int>&used,vector<int>&comp,vector<int>&vec,int k,int v){
        comp[v]=k;
        used[v]=true;
        vec.push_back(v);

        for(auto u:T[v]){
            if(!used[u])visit2(T,used,comp,vec,k,u);
        }
    }

    void decompose(const vector<vector<int>>&G,vector<vector<int>>&H,vector<int>&comp){
        vector<vector<int>>T(G.size());
        for(int i=0;i<G.size();i++){
            for(auto v:G[i]){
                T[v].push_back(i);
            }
        }
        comp.resize(G.size());

        vector<int>vs(G.size());
        vector<int>used(G.size());
        for(int i=0;i<G.size();i++){
            if(!used[i])visit(G,vs,used,i);
        }
        reverse(vs.begin(),vs.end());
        fill(used.begin(),used.end(),0);

        int K=0;
        vector<vector<int>>S;
        for(auto v:vs){
            if(!used[v]){
                S.push_back(vector<int>());
                visit2(T,used,comp,S.back(),K++,v);
            }
        }

        H.resize(K);
        fill(used.begin(),used.end(),0);
        for(int i=0;i<K;i++){
            for(auto v:S[i]){
                for(auto u:G[v]){
                    if(used[comp[u]]||comp[v]==comp[u])continue;
                    used[comp[u]]=true;
                    H[comp[v]].push_back(comp[u]);
                }
            }
            for(auto v:H[i])used[v]=false;
        }

    }
}

vpint add(vpint x,vpint y){
    vpint z;
    rep(i,x.size())z.pb(x[i]);
    rep(i,y.size())z.pb(y[i]);
    sort(all(z));
    vpint w;
    for(auto p:z){
        if(w.size()==0||w.back().se+1<p.fi)w.pb(p);
        else w.back().se=p.se;
    }
    return w;
}

signed main(){
    cin>>N;
    rep(i,N){
        cin>>X[i]>>Y[i]>>R[i];
        L=abs(X[i])+abs(Y[i]);
        int x=X[i]+Y[i];
        int y=X[i]-Y[i];
        X[i]=x;
        Y[i]=y;
    }


    rep(i,N)ps.pb({Y[i],X[i]});
    sort(all(ps),comp);

    vint rrr(N);
    rep(i,N)rrr[id(i)]=R[i];
    rep(i,N)R[i]=rrr[i];

    rep(i,N)ps.pb(ps[i]);


    rep(i,N){
        if(R[i]>=2*L){
            r[i]=(i-1+N)%N;
            continue;
        }
        int lb=0,ub=N;
        while(ub-lb>1){
            int mid=(ub+lb)/2;
            bool flag;
            if(T(ps[i])==T(ps[i+mid]))flag=comp(ps[i],ps[i+mid])&&dist(ps[i],ps[i+mid])<=R[i];
            else if((T(ps[i])+1)%4==T(ps[i+mid]))flag=dist(ps[i],ps[i+mid])<=R[i];
            else flag=false;

            if(flag)lb=mid;
            else ub=mid;
        }
        r[i]=(i+lb)%N;
    }

    rep(i,N){
        if(R[i]>2*L){
            l[i]=i;
            continue;
        }
        int lb=0,ub=N;
        while(ub-lb>1){
            int mid=(ub+lb)/2;
            bool flag;
            if(T(ps[i+N])==T(ps[i+N-mid]))flag=comp(ps[i+N-mid],ps[i+N])&&dist(ps[i+N-mid],ps[i+N])<=R[i];
            else if((T(ps[i+N])+3)%4==T(ps[i+N-mid]))flag=dist(ps[i+N-mid],ps[i+N])<=R[i];
            else flag=false;

            if(flag)lb=mid;
            else ub=mid;
        }
        l[i]=(i+N-lb)%N;
    }


    rep(i,SEG-1){
        G[i].pb(i*2+1);G[i].pb(i*2+2);
    }

    rep(i,N){
        if(l[i]<=r[i]){
            addEdge(l[i],r[i]+1,i+SEG-1);
        }
        else{
            addEdge(l[i],N,i+SEG-1);
            addEdge(0,r[i]+1,i+SEG-1);
        }
    }

    vector<vint>H;
    vint ra;
    SCC::decompose(G,H,ra);
    vector<vpint>dp(H.size());
    rep(i,N){
        int k=ra[i+SEG-1];

        vpint hoge;
        if(l[i]<=r[i])hoge.pb({l[i],r[i]});
        else{
            hoge.pb({0,r[i]});
            hoge.pb({l[i],N-1});
        }
        dp[k]=add(dp[k],hoge);

    }


    /*
    rep(i,N){
        int k=ra[id(i)+SEG-1];
        cout<<k<<endl;
        for(auto p:dp[k])cout<<p.fi<<" "<<p.se<<endl;
        cout<<"---------"<<endl;
    }*/


    for(int i=H.size()-1;i>=0;i--){
        for(auto u:H[i]){
            dp[i]=add(dp[i],dp[u]);
        }
    }

    rep(i,N){
        int k=ra[id(i)+SEG-1];
        int ans=0;
        for(auto p:dp[k])ans+=p.se-p.fi+1;
        cout<<N-ans<<endl;
    }
    return 0;
}
accuracy: 0.13333333333333333
time_ms: 730
memory_kb: 139296
final_rank: 12

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <random>
#include <vector>
#include <array>
#include <bitset>
#include <queue>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); }
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;

struct E {
    int to;
};

struct SCC {
    V<int> id;
    VV<int> groups;
};

template<class E>
struct SCC_EXEC {
    const VV<E> &g;
    int tm = 0;
    V<bool> inS;
    V<int> id, low, ord, st;
    VV<int> groups;
    void dfs(int v) {
        low[v] = ord[v] = tm++;
        st.push_back(v);
        inS[v] = true;
        for (auto e: g[v]) {
            if (ord[e.to] == -1) {
                dfs(e.to);
                low[v] = min(low[v], low[e.to]);
            } else if (inS[e.to]) {
                low[v] = min(low[v], ord[e.to]);
            }
        }
        if (low[v] == ord[v]) {
            V<int> gr;
            while (true) {
                int u = st.back(); st.pop_back();
                gr.push_back(u);
                if (u == v) break;
            }
            for (int x: gr) inS[x] = false;
            groups.push_back(gr);
        }
    }
    SCC info;
    SCC_EXEC(const VV<E> &g) : g(g) {
        int n = int(g.size());
        inS = V<bool>(n); low = V<int>(n); ord = V<int>(n, -1);
        for (int i = 0; i < n; i++) {
            if (ord[i] == -1) dfs(i);
        }
        reverse(begin(groups), end(groups));
        V<int> id(n);
        for (int i = 0; i < int(groups.size()); i++) {
            for (int x: groups[i]) {
                id[x] = i;
            }
        }
        info = SCC{id, groups};
    }
};
template<class E> SCC scc(const VV<E> &g) { return SCC_EXEC<E>(g).info; }

int n, N;
VV<E> g;

void adde(int i, int j) {
//    cout << "adde " << i << " -> " << j << endl;
    g[i].push_back(E{j});
}

struct Node {
    using NP = Node*;
    int sz;
    NP l, r;

    int id;

    Node(int sz, int off) : sz(sz) {
        id = N; N++;
        g.push_back(V<E>{});

        if (sz == 1) {
            adde(id, off);
            return;
        }
        l = new Node(sz/2, off);
        r = new Node(sz-sz/2, off+sz/2);
        adde(id, l->id);
        adde(id, r->id);
    }

    void add(int a, int b, int x) {
        if (b <= 0 || sz <= a) return;
        if (a <= 0 && sz <= b) {
            adde(x, id);
            return;
        }
        l->add(a, b, x);
        r->add(a-sz/2, b-sz/2, x);
    }
};

V<int> solve(const V<int> &le, const V<int> &ri) {
    N = 2*n;
    g = VV<E>(2*n);
    auto tr = new Node(2*n, 0);
    for (int i = 0; i < n; i++) {
        int l = le[i], r = ri[i];
        if (l < r) {
            tr->add(l, r, i);
            tr->add(l+n, r+n, i+n);
        } else {
            if (i < r) {
                tr->add(0, r, i);
                tr->add(l, n+r, n+i);
            } else {
                tr->add(l, n+r, i);
                tr->add(n+l, 2*n, n+i);                
            }
        }
    }
    auto scci = scc(g);
    int m = int(scci.groups.size());
    V<int> dpmi(m, TEN(9)), dpma(m, -TEN(9));

    for (int i = m-1; i >= 0; i--) {
        for (int p: scci.groups[i]) {
            if (p < 2*n) {
                dpmi[i] = min(dpmi[i], p);
                dpma[i] = max(dpma[i], p);
            }
            assert(0 <= p && p < g.size());
            for (auto e: g[p]) {
                int q = e.to;
                //p -> q
                int j = scci.id[q];
                dpmi[i] = min(dpmi[i], dpmi[j]);
                dpma[i] = max(dpma[i], dpma[j]);
            }
        }
    }

    V<int> v(n);
    for (int p = 0; p < n; p++) {
        int i = scci.id[p];
        int ni = scci.id[n+p];
//        int l = dpmi[ni] - n, r = dpma[i];
        int l = min(dpmi[i], dpmi[ni] - n);
        int r = max(dpma[i], dpma[ni] - n);
//        cout << p << " " << l << " " << r << endl;
        v[p] = n-min(n, r-l+1);
    }
    return v;
}


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(20);

    cin >> n;
    using P = pair<ll, ll>;
    using T = tuple<ll, P, ll>; // pid, pos, rad
    V<T> v(n);

    ll R;
    for (int i = 0; i < n; i++) {
        ll x, y, r, pid;
        cin >> x >> y >> r;
        R = abs(x) + abs(y);

        if (x >= 0 && y >= 0) {
            pid = y;
        } else if (x <= 0 && y >= 0) {
            pid = R - x;
        } else if (x <= 0 && y <= 0) {
            pid = 2*R - y;
        } else {
            pid = 3*R + x;
        }
        v[i] = T(pid, P(x, y), r);
    }

    V<int> idx(n);
    iota(begin(idx), end(idx), 0);
    sort(begin(idx), end(idx), [&](int a, int b){
        return v[a] < v[b];
    });

    V<P> p(2*n);
    V<ll> pid(2*n), r(2*n);

    for (int i = 0; i < n; i++) {
        tie(pid[i], p[i], r[i]) = v[idx[i]];
        tie(pid[n+i], p[n+i], r[n+i]) = v[idx[i]];
        pid[n+i] += 4*R;
    }

    auto hit = [&](int i, int j) {
        int di = 0;
        di += abs(p[i].first - p[j].first);
        di += abs(p[i].second - p[j].second);
        return di <= r[i];
    };

    V<int> le(n), ri(n);
    //left
    for (int i = 0; i < n; i++) {        
        int l, r = n+i;
        l = lower_bound(begin(pid), end(pid), pid[i] + 2*R) - begin(pid) - 1;
        while (r-l > 1) {
            int md = (l+r)/2;
            if (!hit(n+i, md)) {
                l = md;
            } else {
                r = md;
            }
        }
        le[i] = r;
    }

    //right
    for (int i = 0; i < n; i++) {        
        int l = i, r;
        r = lower_bound(begin(pid), end(pid), pid[i] + 2*R) - begin(pid);
        while (r-l > 1) {
            int md = (l+r)/2;
            if (hit(i, md)) {
                l = md;
            } else {
                r = md;
            }
        }
        ri[i] = n+r;
    }

    for (int i = 0; i < n; i++) {
        if (ri[i] - le[i] >= n) {
            le[i] = 0; ri[i] = n;
        } else {
            le[i] %= n; ri[i] %= n;
        }
    }
/*    for (int i = 0; i < n; i++) {
        cout << idx[i] << ", ";
    }
    cout << endl;
    for (int i = 0; i < n; i++) {
        cout << p[i].first << " " << p[i].second << " " << le[i] << " " << ri[i] << endl;
    }*/

    V<int> ans = solve(le, ri);
    V<int> lst(n);
    for (int i = 0; i < n; i++) {
        lst[idx[i]] = ans[i];
    }

    for (int d: lst) {
        cout << d << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 580
memory_kb: 233488
final_rank: 8

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <random>
#include <vector>
#include <array>
#include <bitset>
#include <queue>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); }
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;

struct E {
    int to;
};

struct SCC {
    V<int> id;
    VV<int> groups;
};

template<class E>
struct SCC_EXEC {
    const VV<E> &g;
    int tm = 0;
    V<bool> inS;
    V<int> id, low, ord, st;
    VV<int> groups;
    void dfs(int v) {
        low[v] = ord[v] = tm++;
        st.push_back(v);
        inS[v] = true;
        for (auto e: g[v]) {
            if (ord[e.to] == -1) {
                dfs(e.to);
                low[v] = min(low[v], low[e.to]);
            } else if (inS[e.to]) {
                low[v] = min(low[v], ord[e.to]);
            }
        }
        if (low[v] == ord[v]) {
            V<int> gr;
            while (true) {
                int u = st.back(); st.pop_back();
                gr.push_back(u);
                if (u == v) break;
            }
            for (int x: gr) inS[x] = false;
            groups.push_back(gr);
        }
    }
    SCC info;
    SCC_EXEC(const VV<E> &g) : g(g) {
        int n = int(g.size());
        inS = V<bool>(n); low = V<int>(n); ord = V<int>(n, -1);
        for (int i = 0; i < n; i++) {
            if (ord[i] == -1) dfs(i);
        }
        reverse(begin(groups), end(groups));
        V<int> id(n);
        for (int i = 0; i < int(groups.size()); i++) {
            for (int x: groups[i]) {
                id[x] = i;
            }
        }
        info = SCC{id, groups};
    }
};
template<class E> SCC scc(const VV<E> &g) { return SCC_EXEC<E>(g).info; }

int n, N;
VV<E> g;

void adde(int i, int j) {
//    cout << "adde " << i << " -> " << j << endl;
    g[i].push_back(E{j});
}

struct Node {
    using NP = Node*;
    int sz;
    NP l, r;

    int id;

    Node(int sz, int off) : sz(sz) {
        id = N; N++;
        g.push_back(V<E>{});

        if (sz == 1) {
            adde(id, off);
            return;
        }
        l = new Node(sz/2, off);
        r = new Node(sz-sz/2, off+sz/2);
        adde(id, l->id);
        adde(id, r->id);
    }

    void add(int a, int b, int x) {
        if (b <= 0 || sz <= a) return;
        if (a <= 0 && sz <= b) {
            adde(x, id);
            return;
        }
        l->add(a, b, x);
        r->add(a-sz/2, b-sz/2, x);
    }
};

V<int> solve(const V<int> &le, const V<int> &ri) {
    N = 2*n;
    g = VV<E>(2*n);
    auto tr = new Node(2*n, 0);
    for (int i = 0; i < n; i++) {
        int l = le[i], r = ri[i];
        if (l < r) {
            tr->add(l, r, i);
            tr->add(l+n, r+n, i+n);
        } else {
            if (i < r) {
                tr->add(0, r, i);
                tr->add(l, n+r, n+i);
            } else {
                tr->add(l, n+r, i);
                tr->add(n+l, 2*n, n+i);                
            }
        }
    }
    auto scci = scc(g);
    int m = int(scci.groups.size());
    V<int> dpmi(m, TEN(9)), dpma(m, -TEN(9));

    for (int i = m-1; i >= 0; i--) {
        for (int p: scci.groups[i]) {
            if (p < 2*n) {
                dpmi[i] = min(dpmi[i], p);
                dpma[i] = max(dpma[i], p);
            }
            assert(0 <= p && p < g.size());
            for (auto e: g[p]) {
                int q = e.to;
                //p -> q
                int j = scci.id[q];
                dpmi[i] = min(dpmi[i], dpmi[j]);
                dpma[i] = max(dpma[i], dpma[j]);
            }
        }
    }

    V<int> v(n);
    for (int p = 0; p < n; p++) {
        int i = scci.id[p];
        int ni = scci.id[n+p];
        int l = dpmi[ni] - n, r = dpma[i];
//        cout << p << " " << l << " " << r << endl;
        v[p] = n-min(n, r-l+1);
    }
    return v;
}


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(20);

    cin >> n;
    using P = pair<ll, ll>;
    using T = tuple<ll, P, ll>; // pid, pos, rad
    V<T> v(n);

    ll R;
    for (int i = 0; i < n; i++) {
        ll x, y, r, pid;
        cin >> x >> y >> r;
        R = abs(x) + abs(y);

        if (x >= 0 && y >= 0) {
            pid = y;
        } else if (x <= 0 && y >= 0) {
            pid = R - x;
        } else if (x <= 0 && y <= 0) {
            pid = 2*R - y;
        } else {
            pid = 3*R + x;
        }
        v[i] = T(pid, P(x, y), r);
    }

    V<int> idx(n);
    iota(begin(idx), end(idx), 0);
    sort(begin(idx), end(idx), [&](int a, int b){
        return v[a] < v[b];
    });

    V<P> p(2*n);
    V<ll> pid(2*n), r(2*n);

    for (int i = 0; i < n; i++) {
        tie(pid[i], p[i], r[i]) = v[idx[i]];
        tie(pid[n+i], p[n+i], r[n+i]) = v[idx[i]];
        pid[n+i] += 4*R;
    }

    auto hit = [&](int i, int j) {
        int di = 0;
        di += abs(p[i].first - p[j].first);
        di += abs(p[i].second - p[j].second);
        return di <= r[i];
    };

    V<int> le(n), ri(n);
    //left
    for (int i = 0; i < n; i++) {        
        int l, r = n+i;
        l = lower_bound(begin(pid), end(pid), pid[i] + 2*R) - begin(pid) - 1;
        while (r-l > 1) {
            int md = (l+r)/2;
            if (!hit(n+i, md)) {
                l = md;
            } else {
                r = md;
            }
        }
        le[i] = r;
    }

    //right
    for (int i = 0; i < n; i++) {        
        int l = i, r;
        r = lower_bound(begin(pid), end(pid), pid[i] + 2*R) - begin(pid);
        while (r-l > 1) {
            int md = (l+r)/2;
            if (hit(i, md)) {
                l = md;
            } else {
                r = md;
            }
        }
        ri[i] = n+r;
    }

    for (int i = 0; i < n; i++) {
        if (ri[i] - le[i] >= n) {
            le[i] = 0; ri[i] = n;
        } else {
            le[i] %= n; ri[i] %= n;
        }
    }
/*    for (int i = 0; i < n; i++) {
        cout << idx[i] << ", ";
    }
    cout << endl;
    for (int i = 0; i < n; i++) {
        cout << p[i].first << " " << p[i].second << " " << le[i] << " " << ri[i] << endl;
    }*/

    V<int> ans = solve(le, ri);
    V<int> lst(n);
    for (int i = 0; i < n; i++) {
        lst[idx[i]] = ans[i];
    }

    for (int d: lst) {
        cout << d << endl;
    }
    return 0;
}
accuracy: 0.36666666666666664
time_ms: 590
memory_kb: 233384
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define MAX 200005
typedef pair<int,int> Data;
typedef complex<int> Point;
typedef pair<double,int> Pair;
const double PI = acos(-1);

Data merge(Data a,Data b){
  return Data( min(a.first,b.first) , max(a.second,b.second) );
}

const int segN=(1<<20);
struct segtree{
  Data t[ segN*2 ];
  
  void Update(int i,Data d){
    i+=(segN-1);
    t[i]=d;
    while(i){
      i=(i-1)/2;
      t[i]=merge(t[i*2+1],t[i*2+2]);
    }
  }
  
  Data Get(int a,int b,int k=0,int l=0,int r=segN){
    if( b<=l || r<=a ){
      return Data(a,b);
    }
    if( a<=l && r<=b ){
      return t[k];
    }
    int m=(l+r)/2;
    Data lv=Get(a,b,k*2+1,l,m);
    Data rv=Get(a,b,k*2+2,m,r);
    return merge(lv,rv);
  }
};

int calc(Point a){
  return abs( a.real() ) + abs( a.imag() );
}

int calc(Point a,Point b){
  return calc(a-b);
}

double Arg(Point a){
  complex<double> b( a.real(), a.imag() );
  return arg(b);
}

int n;
int x[MAX];
int y[MAX];
Point p[MAX];
int r[MAX];


segtree T;

int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>x[i]>>y[i]>>r[i];
    p[i]=Point(x[i],y[i]);
  }
  
  vector<Pair> v(n*3);
  for(int i=0;i<n;i++){
    v[i]=Pair( Arg(p[i]) , i );
    v[i+n]=Pair( Arg(p[i])+2.0*PI , i );
    v[i+n+n]=Pair( Arg(p[i])+4.0*PI , i );
  }
  sort(v.begin(),v.end());
  vector<Point> w(n*3);
  vector<int> R(n*3);
  for(int i=0;i<n*3;i++){
    w[i]=p[ v[i].second%n ];
    R[i]=r[ v[i].second%n ];
  }

  vector<int> lv(n*3),rv(n*3);
  for(int i=n;i<n*2;i++){
    if( R[i] >= calc(w[i])*2 ){
      lv[i]=0;
      rv[i]=n*3;
      continue;
    }
    
    vector<Pair> :: iterator it;
    int right,left,mid;
    
    it = lower_bound( v.begin(), v.end(), Pair( v[i].first-PI , -1 ) );
    left=it-v.begin();
    right=i;
    while(left<right){
      mid=(left+right)/2;
      if( calc(w[i],w[mid]) <= R[i] ){
        right=mid;
      }else{
        left=mid+1;
      }
    }
    lv[i]=left;
    
    it = lower_bound( v.begin(), v.end(), Pair( v[i].first+PI , -1 ) );
    right=it-v.begin();

    left=i;
    
    while( left<right ){
      mid=(left+right)/2;
      if( calc(w[i],w[mid]) <= R[i] ){
        left=mid+1;
      }else{
        right=mid;
      }
    }
    rv[i]=left;
  }

  //  for(int i=0;i<3*n;i++)cout<<i<<' '<<w[i]<<' '<<R[i]<<endl;
  
  for(int i=0;i<3*n;i++){
    T.Update(i, Data(i,i+1) );
  }
  
  for(int i=n;i<n*2;i++){
    T.Update(i, Data( lv[i], rv[i] ) );
  }
  
  for(int tc=0;tc<20;tc++){
    
    for(int i=0;i<n;i++){
      Data tmp=T.Get(i+n,i+n+1);
      Data base=tmp;
      base.first-=n;
      base.second-=n;
      if(base.first<0)base.first=0;
      if(base.second>n*3)base.second=n*3;
      T.Update(i, base);
      base=tmp;
      base.first+=n;
      base.second+=n;
      if(base.first<0)base.first=0;
      if(base.second>n*3)base.second=n*3;
      T.Update(i+n*2,base);
    }

    for(int i=n;i<n*2;i++){
      Data base=T.Get(i,i+1);
      Data A=T.Get( base.first , base.second );
      T.Update( i, A );
    }
  }

  map<int,int> mp;
  for(int i=n;i<n*2;i++){
    Data tmp=T.Get(i,i+1);
    int len=tmp.second-tmp.first;
    mp[ v[i].second%n ]=max(0, n-len);
  }
  for(int i=0;i<n;i++){
    cout<<mp[i]<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 2070
memory_kb: 53788
final_rank: 5

code_snippet: #include <bits/stdc++.h>
#define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
#define pr(...) GET_MACRO(__VA_ARGS__,pr5,pr4,pr3,pr2,pr1)(__VA_ARGS__)
#define pr1(a) (#a)<<"="<<(a)
#define pr2(a,b) pr1(a)<<", "<<pr1(b)
#define pr3(a,b,c) pr2(a,b)<<", "<<pr1(c)
#define pr4(a,b,c,d) pr3(a,b,c)<<", "<<pr1(d)
#define pr5(a,b,c,d,e) pr4(a,b,c,d)<<", "<<pr1(e)
#define int long long
#define double long double
using namespace std;
const int N = 100010;
const int INF = 1LL<<55;
//const int INF = 1e9;
typedef pair<int,int> P;
typedef long long ll;
template<class T> T Max(T &a,T b){return a=max(a,b);}
template<class T> T Min(T &a,T b){return a=min(a,b);}
ostream& operator<<(ostream& o,P p){return o<<"("<<p.first<<","<<p.second<<")";}
istream& operator>>(istream& i,P &p){return i>>p.first>>p.second;}
typedef tuple<int,int,int,int> T; //x,y,r,idx;
ostream& operator<<(ostream& o,T &a){
  return o <<"( x="<<get<0>(a)<<", y="<<get<1>(a)<<", r="<<get<2>(a)<<", idx="<<get<3>(a)<<")";
}

class RMQ{
public:
  //int INF = 1e9;
  int INF = 1LL<<55;
  int n;
  vector<int> dat;
  int flag; // Range Max Queryにしたいときはflag=1にする。
  
  //初期化
  RMQ(){n=-1;}
  RMQ(int n_,int flag = 0){
    this->flag = flag;
    n=1;
    while(n<n_)n*=2;
    dat.resize(2*n-1,INF);
  }
  
  //k番目の値をaに変更
  void update(int k,int a){
    assert(a >= 0);
    if(flag) a *= -1;
    k+=n-1;
    assert(dat[k] >= a);
    
    dat[k]=a;
    while(k>0){
      k=(k-1)/2;
      dat[k]=min(dat[k*2+1],dat[k*2+2]);
    }
  }

  int value(int k){return (flag?-1:1) * dat[k+n-1];}
  
  //[a,b)の最小値を求める query(a,b,0,0,n)
  int query(int a,int b,int k=0,int l=0,int r=-1){
    if(r == -1) r = n, assert(a < n && b <= n);
    if(r<=a||b<=l)return INF;
    if(a<=l&&r<=b)return k == 0 && flag? -dat[k]:dat[k];
    int vl=query(a,b,k*2+1,l,(l+r)/2);
    int vr=query(a,b,k*2+2,(l+r)/2,r);
    int res = min(vl,vr);
    if(k == 0 && flag) res *= -1;
    return res;
  }

};


//rが小さい順に処理する。
RMQ initTo(const vector<T> &A){

  auto getDisT=[&](const T &a,const T &b){
    int x1,y1; tie(x1,y1,ignore,ignore) = a;
    int x2,y2; tie(x2,y2,ignore,ignore) = b;
    return abs(x1 - x2) + abs(y1 - y2);
  };
  auto getDis=[&](int i,int j){return getDisT(A[i],A[j]);};
  
  int n = A.size();
  RMQ res(n,1);
  vector<int> Idx(n);
  for(int i=0;i<n;i++) Idx[i] = i;

  sort(Idx.begin(),Idx.end(),[&](int a,int b){
      int r1 = get<2>(A[a]);
      int r2 = get<2>(A[b]);
      return r1 < r2;
    });
  
  RMQ mem(n,1);
  function<int(int,int)> search=[&](int pos,int start){
    const int r = get<2>(A[start]);
    if(getDis(start,pos) > r) return pos;
    if(pos + 1 >=n || getDis(start,pos+1) > r) return pos;
    int nx = mem.value(pos);
    if(nx == -INF || nx == pos) nx = pos+1;
    int to = search(nx,start);
    mem.update(pos,to);
    return to;
  };
  
  for(int i=0;i<n;i++) {
    int to=search(Idx[i],Idx[i]);
    res.update(Idx[i],to);
    mem.update(Idx[i],to);
  }
  return res;
}

int dfs(int pos,RMQ &To){
  int l = pos, r = To.value(pos);
  int to = To.query(l,r+1);
  if(to == pos) return pos;
  int res = dfs(to,To);
  To.update(pos,res);
  return res;
}

int dfs2(int pos,RMQ &To,RMQ &rTo,int n){
  int rpos = 2 * n - 1 - pos%n;
  int lmax = dfs(rpos,rTo) - rpos;
  int lto = dfs( To.query(max(0LL,pos - lmax),pos+1), To );
  int rto = dfs(pos,To);
  int to = max(lto,rto);
  if(lto > rto) to = dfs2(lto,To,rTo,n);
  To.update(pos,to);
  return to;
}

signed main(){
  int n;
  cin>>n;
  vector<T> A(n),rA;
  
  set<P> used;
  for(int i=0;i<n;i++){
    int x,y,r;
    scanf("%lld%lld%lld",&x,&y,&r);
    assert(used.count(P(x,y)) == 0);
    used.insert(P(x,y));
    A[i] = T(x,y,r,i);
  }

  sort(A.begin(),A.end(),[&](T &a,T &b){
      typedef complex<double> P;
      double x1,y1; tie(x1,y1,ignore,ignore) = a;
      double x2,y2; tie(x2,y2,ignore,ignore) = b;
      return arg(P(x1,y1)) < arg(P(x2,y2));
    });
  
  for(int i=0;i<2*n;i++) A.push_back(A[i%n]);
  rA = A; reverse(rA.begin(),rA.end());

  RMQ To = initTo(A);
  RMQ rTo = initTo(rA);
  
  vector<int> ans(n);
  int update = 1;
  while(update){
    update = 0;
    for(int i=n;i<2*n;i++){
      int ri = (2 * n - 1) - i%n;
      int idx = get<3>(A[i]);
      int to = dfs2(i,To,rTo,n);
      int rto = dfs2(ri,rTo,To,n);
      int num = to - i + 1;
      int rnum = rto - ri + 1;
      assert(A[i] == rA[ri]);
      int score = min(n,num+rnum-1);
      update |= ans[idx] < score;
      ans[idx] = score;
    }
  }    
  for(int a:ans) printf("%lld\n",n - a);
  return 0;
}
accuracy: 1
time_ms: 2290
memory_kb: 125716
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;

template <typename T,typename E>
struct SegmentTree{
  using F = function<T(T,T)>;
  using G = function<T(T,E)>;
  Int n;
  F f;
  G g;
  T ti;
  vector<T> dat;
  SegmentTree(){};
  SegmentTree(Int n_,F f,G g,T ti):
    f(f),g(g),ti(ti){
    init(n_);
  }
  void init(Int n_){
    n=1;
    while(n<n_) n*=2;
    dat.assign(2*n-1,ti);
  }
  void build(Int n_, vector<T> v){
    for(Int i=0;i<n_;i++) dat[i+n-1]=v[i];
    for(Int i=n-2;i>=0;i--)
      dat[i]=f(dat[i*2+1],dat[i*2+2]);
  }
  void update(Int k,E a){
    k+=n-1;
    dat[k]=g(dat[k],a);
    while(k>0){
      k=(k-1)/2;
      dat[k]=f(dat[k*2+1],dat[k*2+2]);
    }
  }
  inline T query(Int a,Int b){
    T vl=ti,vr=ti;
    for(Int l=a+n,r=b+n;l<r;l>>=1,r>>=1) {
      if(l&1) vl=f(vl,dat[(l++)-1]);
      if(r&1) vr=f(dat[(--r)-1],vr);
    }
    return f(vl,vr);
  }

  Int find(Int a,Int b,function<bool(T)> &check,Int k,Int l,Int r){
    if(!check(dat[k])||r<=a||b<=l) return -1;
    if(k>=n-1) return k-(n-1);
    Int m=(l+r)>>1;
    Int vl=find(a,b,check,k*2+1,l,m);
    if(~vl) return vl;
    return find(a,b,check,k*2+2,m,r);
  }
  
  Int find(Int a,Int b,function<bool(T)> &check){
    return find(a,b,check,0,0,n);
  }
  
};

//INSERT ABOVE HERE
signed main(){
  Int n;
  cin>>n;
  using T = tuple<Int, Int, Int>;
  vector<T> v(n);
  map<T, Int> m;
  for(Int i=0;i<n;i++){
    Int x,y,r;
    cin>>x>>y>>r;
    v[i]=T(x+y,x-y,r);
    m[v[i]]=i;
  }
  
  sort(v.begin(),v.end(),[&](T a,T b){
      Int au,av,ar;
      tie(au,av,ar)=a;
      Int bu,bv,br;
      tie(bu,bv,br)=b;
      return atan2(av,au)<atan2(bv,bu);
    });

  for(Int i=0;i<n;i++) v.emplace_back(T(v[i]));
  for(Int i=0;i<n;i++) v.emplace_back(T(v[i]));

  using P = pair<Int, Int>;
  SegmentTree<P, P>::F f=[&](P a,P b){
    return P(min(a.first,b.first),max(a.second,b.second));};


  Int N=n*3;
  SegmentTree<P, P> seg(N,f,f,P(N,-1));
  for(Int i=0;i<N;i++) seg.update(i,P(i,i));

  auto check=[&](Int a,Int b){
    return max(abs(get<0>(v[a])-get<0>(v[b])),
	       abs(get<1>(v[a])-get<1>(v[b])))<=(get<2>(v[b]));
  };
  
  vector<Int> dp(N,N);
  for(Int i=0;i<N;i++){
    dp[i]=i;
    while(0<dp[i]&&check(dp[i]-1,i)) dp[i]=dp[dp[i]-1];
    seg.update(i,P(dp[i],dp[i]));
  }
  fill(dp.begin(),dp.end(),-1);
  for(Int i=N-1;i>=0;i--){
    dp[i]=i;
    while(dp[i]+1<N&&check(dp[i]+1,i)) dp[i]=dp[dp[i]+1];
    seg.update(i,P(dp[i],dp[i]));
  }
  
  Int flg=1;
  while(flg){
    flg=0;
    for(Int i=0;i<N;i++){
      auto a=seg.query(i,i+1);
      auto b=seg.query(a.first,a.second+1);
      flg|=(a!=b);
      seg.update(i,b);
    }
  }

  vector<Int> ans(n);
  for(Int i=0;i<n;i++){
    Int idx=m[v[i]];
    auto a=seg.query(n+i,n+i+1);
    Int k=(i-a.first+1)+(a.second-i+1)-1;
    ans[idx]=min(k,n);
  }
  
  for(Int i=0;i<n;i++) cout<<n-ans[i]<<endl;
  return 0;
}
accuracy: 1
time_ms: 1220
memory_kb: 71820
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;

template <typename T,typename E>
struct SegmentTree{
  using F = function<T(T,T)>;
  using G = function<T(T,E)>;
  int n;
  F f;
  G g;
  T ti;
  vector<T> dat;
  SegmentTree(){};
  SegmentTree(int n_,F f,G g,T ti):
    f(f),g(g),ti(ti){
    init(n_);
  }
  void init(int n_){
    n=1;
    while(n<n_) n*=2;
    dat.assign(2*n-1,ti);
  }
  void build(int n_, vector<T> v){
    for(int i=0;i<n_;i++) dat[i+n-1]=v[i];
    for(int i=n-2;i>=0;i--)
      dat[i]=f(dat[i*2+1],dat[i*2+2]);
  }
  void update(int k,E a){
    k+=n-1;
    dat[k]=g(dat[k],a);
    while(k>0){
      k=(k-1)/2;
      dat[k]=f(dat[k*2+1],dat[k*2+2]);
    }
  }
  inline T query(int a,int b){
    T vl=ti,vr=ti;
    for(int l=a+n,r=b+n;l<r;l>>=1,r>>=1) {
      if(l&1) vl=f(vl,dat[(l++)-1]);
      if(r&1) vr=f(dat[(--r)-1],vr);
    }
    return f(vl,vr);
  }

  int find(int a,int b,function<bool(T)> &check,int k,int l,int r){
    if(!check(dat[k])||r<=a||b<=l) return -1;
    if(k>=n-1) return k-(n-1);
    int m=(l+r)>>1;
    int vl=find(a,b,check,k*2+1,l,m);
    if(~vl) return vl;
    return find(a,b,check,k*2+2,m,r);
  }
  
  int find(int a,int b,function<bool(T)> &check){
    return find(a,b,check,0,0,n);
  }
  
};

//INSERT ABOVE HERE
signed main(){
  int n;
  cin>>n;
  using T = tuple<int, int, int>;
  vector<T> v(n);
  map<T, int> m;
  for(int i=0;i<n;i++){
    int x,y,r;
    cin>>x>>y>>r;
    v[i]=T(x+y,x-y,r);
    m[v[i]]=i;
  }
  
  sort(v.begin(),v.end(),[&](T a,T b){
      int au,av,ar;
      tie(au,av,ar)=a;
      int bu,bv,br;
      tie(bu,bv,br)=b;
      return atan2(av,au)<atan2(bv,bu);
    });

  for(int i=0;i<n;i++) v.emplace_back(T(v[i]));
  for(int i=0;i<n;i++) v.emplace_back(T(v[i]));

  using P = pair<int, int>;
  SegmentTree<P, P>::F f=[&](P a,P b){
    return P(min(a.first,b.first),max(a.second,b.second));};


  int N=n*3;
  SegmentTree<P, P> seg(N,f,f,P(N,-1));
  for(int i=0;i<N;i++) seg.update(i,P(i,i));

  auto check=[&](int a,int b){
    return max(abs(get<0>(v[a])-get<0>(v[b])),
	       abs(get<1>(v[a])-get<1>(v[b])))<=(get<2>(v[b]));
  };
  
  vector<int> dp(N,N);
  for(int i=0;i<N;i++){
    dp[i]=i;
    while(0<dp[i]&&check(dp[i]-1,i)) dp[i]=dp[dp[i]-1];
    //cout<<i<<":"<<dp[i]<<endl;
    seg.update(i,P(dp[i],dp[i]));
  }
  fill(dp.begin(),dp.end(),-1);
  for(int i=N-1;i>=0;i--){
    dp[i]=i;
    while(dp[i]+1<N&&check(dp[i]+1,i)) dp[i]=dp[dp[i]+1];
    //cout<<i<<":"<<dp[i]<<endl;
    seg.update(i,P(dp[i],dp[i]));
  }
  
  int flg=1;
  while(flg){
    flg=0;
    for(int i=0;i<N;i++){
      auto a=seg.query(i,i+1);
      auto b=seg.query(a.first,a.second+1);
      flg|=(a!=b);
      //if(a!=b) cout<<a.first<<" "<<a.second<<":"<<b.first<<" "<<b.second<<endl;
      seg.update(i,b);
    }
  }

  vector<int> ans(n);
  for(int i=0;i<n;i++){
    int idx=m[v[i]];
    auto a=seg.query(n+i,n+i+1);
    int k=(i-a.first+1)+(a.second-i+1)-1;
    ans[idx]=min(k,n);
  }
  
  for(int i=0;i<n;i++) cout<<n-ans[i]<<endl;
  return 0;
}
accuracy: 1
time_ms: 1250
memory_kb: 42096
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
#define pr(...) GET_MACRO(__VA_ARGS__,pr5,pr4,pr3,pr2,pr1)(__VA_ARGS__)
#define pr1(a) (#a)<<"="<<(a)
#define pr2(a,b) pr1(a)<<", "<<pr1(b)
#define pr3(a,b,c) pr2(a,b)<<", "<<pr1(c)
#define pr4(a,b,c,d) pr3(a,b,c)<<", "<<pr1(d)
#define pr5(a,b,c,d,e) pr4(a,b,c,d)<<", "<<pr1(e)
#define int long long
#define double long double
using namespace std;
const int N = 100010;
const int INF = 1LL<<55;
//const int INF = 1e9;
typedef pair<int,int> P;
typedef long long ll;
template<class T> T Max(T &a,T b){return a=max(a,b);}
template<class T> T Min(T &a,T b){return a=min(a,b);}
ostream& operator<<(ostream& o,P p){return o<<"("<<p.first<<","<<p.second<<")";}
istream& operator>>(istream& i,P &p){return i>>p.first>>p.second;}
typedef tuple<int,int,int,int> T; //x,y,r,idx;
ostream& operator<<(ostream& o,T &a){
  return o <<"( x="<<get<0>(a)<<", y="<<get<1>(a)<<", r="<<get<2>(a)<<", idx="<<get<3>(a)<<")";
}

class RMQ{
public:
  //int INF = 1e9;
  int INF = 1LL<<55;
  int n;
  vector<int> dat;
  int flag; // Range Max Queryにしたいときはflag=1にする。
  
  //初期化
  RMQ(){n=-1;}
  RMQ(int n_,int flag = 0){
    this->flag = flag;
    n=1;
    while(n<n_)n*=2;
    dat.resize(2*n-1,INF);
  }
  
  //k番目の値をaに変更
  void update(int k,int a){
    assert(a >= 0);
    if(flag) a *= -1;
    k+=n-1;
    assert(dat[k] >= a);
    
    dat[k]=a;
    while(k>0){
      k=(k-1)/2;
      dat[k]=min(dat[k*2+1],dat[k*2+2]);
    }
  }

  int value(int k){return (flag?-1:1) * dat[k+n-1];}
  
  //[a,b)の最小値を求める query(a,b,0,0,n)
  int query(int a,int b,int k=0,int l=0,int r=-1){
    if(r == -1) r = n, assert(a < n && b <= n);
    if(r<=a||b<=l)return INF;
    if(a<=l&&r<=b)return k == 0 && flag? -dat[k]:dat[k];
    int vl=query(a,b,k*2+1,l,(l+r)/2);
    int vr=query(a,b,k*2+2,(l+r)/2,r);
    int res = min(vl,vr);
    if(k == 0 && flag) res *= -1;
    return res;
  }

};


//rが小さい順に処理する。
RMQ initTo(const vector<T> &A){

  auto getDisT=[&](const T &a,const T &b){
    int x1,y1; tie(x1,y1,ignore,ignore) = a;
    int x2,y2; tie(x2,y2,ignore,ignore) = b;
    return abs(x1 - x2) + abs(y1 - y2);
  };
  auto getDis=[&](int i,int j){return getDisT(A[i],A[j]);};
  
  int n = A.size();
  RMQ res(n,1);
  vector<int> Idx(n);
  for(int i=0;i<n;i++) Idx[i] = i;

  sort(Idx.begin(),Idx.end(),[&](int a,int b){
      int r1 = get<2>(A[a]);
      int r2 = get<2>(A[b]);
      return r1 < r2;
    });
  
  RMQ mem(n,1);
  function<int(int,int)> search=[&](int pos,int start){
    const int r = get<2>(A[start]);
    if(getDis(start,pos) > r) return pos;
    if(pos + 1 >=n || getDis(start,pos+1) > r) return pos;
    int nx = mem.value(pos);
    if(nx == -INF || nx == pos) nx = pos+1;
    int to = search(nx,start);
    mem.update(pos,to);
    return to;
  };
  
  for(int i=0;i<n;i++) {
    int to=search(Idx[i],Idx[i]);
    res.update(Idx[i],to);
    mem.update(Idx[i],to);
  }
  return res;
}

int dfs(int pos,RMQ &To){
  int l = pos, r = To.value(pos);
  int to = To.query(l,r+1);
  if(to == pos) return pos;
  int res = dfs(to,To);
  To.update(pos,res);
  return res;
}

int dfs2(int pos,RMQ &To,RMQ &rTo,int n){
  int rpos = 2 * n - 1 - pos%n;
  int lmax = dfs(rpos,rTo) - rpos;
  int lto = dfs( To.query(max(0LL,pos - lmax),pos+1), To );
  int rto = dfs(pos,To);
  int to = max(lto,rto);
  if(lto > rto) to = dfs2(lto,To,rTo,n);
  To.update(pos,to);
  return to;
}

signed main(){
  int n;
  cin>>n;
  vector<T> A(n),rA;
  
  for(int i=0;i<n;i++){
    int x,y,r;
    scanf("%lld%lld%lld",&x,&y,&r);
    A[i] = T(x,y,r,i);
  }

  sort(A.begin(),A.end(),[&](T &a,T &b){
      typedef complex<double> P;
      double x1,y1; tie(x1,y1,ignore,ignore) = a;
      double x2,y2; tie(x2,y2,ignore,ignore) = b;
      return arg(P(x1,y1)) < arg(P(x2,y2));
    });
  
  for(int i=0;i<2*n;i++) A.push_back(A[i%n]);
  rA = A; reverse(rA.begin(),rA.end());

  RMQ To = initTo(A);
  RMQ rTo = initTo(rA);
  
  vector<int> ans(n);
  int update = 1;
  while(update){
    update = 0;
    for(int i=n;i<2*n;i++){
      int ri = (2 * n - 1) - i%n;
      int idx = get<3>(A[i]);
      int to = dfs2(i,To,rTo,n);
      int rto = dfs2(ri,rTo,To,n);
      int num = to - i + 1;
      int rnum = rto - ri + 1;
      assert(A[i] == rA[ri]);
      int score = min(n,num+rnum-1);
      update |= ans[idx] < score;
      ans[idx] = score;
    }
  }    
  for(int a:ans) printf("%lld\n",n - a);
  return 0;
}
accuracy: 1
time_ms: 2250
memory_kb: 113216
final_rank: 9

code_snippet: #include <bits/stdc++.h>
#define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
#define pr(...) GET_MACRO(__VA_ARGS__,pr5,pr4,pr3,pr2,pr1)(__VA_ARGS__)
#define pr1(a) (#a)<<"="<<(a)
#define pr2(a,b) pr1(a)<<", "<<pr1(b)
#define pr3(a,b,c) pr2(a,b)<<", "<<pr1(c)
#define pr4(a,b,c,d) pr3(a,b,c)<<", "<<pr1(d)
#define pr5(a,b,c,d,e) pr4(a,b,c,d)<<", "<<pr1(e)
//#define int long long
#define double long double
using namespace std;
const int N = 100010;
//const int INF = 1LL<<55;
const int INF = 1e9;
typedef pair<int,int> P;
typedef long long ll;
template<class T> T Max(T &a,T b){return a=max(a,b);}
template<class T> T Min(T &a,T b){return a=min(a,b);}
ostream& operator<<(ostream& o,P p){return o<<"("<<p.first<<","<<p.second<<")";}
istream& operator>>(istream& i,P &p){return i>>p.first>>p.second;}
typedef tuple<int,int,int,int> T; //x,y,r,idx;
ostream& operator<<(ostream& o,T &a){
  return o <<"( x="<<get<0>(a)<<", y="<<get<1>(a)<<", r="<<get<2>(a)<<", idx="<<get<3>(a)<<")";
}

class RMQ{
public:
  int INF = 1e9;
  int n;
  vector<int> dat;
  int flag; // Range Max Queryにしたいときはflag=1にする。
  
  //初期化
  RMQ(){n=-1;}
  RMQ(int n_,int flag = 0){
    this->flag = flag;
    n=1;
    while(n<n_)n*=2;
    dat.resize(2*n-1,INF);
  }
  
  //k番目の値をaに変更
  void update(int k,int a){
    assert(a >= 0);
    if(flag) a *= -1;
    k+=n-1;
    assert(dat[k] >= a);
    
    dat[k]=a;
    while(k>0){
      k=(k-1)/2;
      dat[k]=min(dat[k*2+1],dat[k*2+2]);
    }
  }

  int value(int k){return (flag?-1:1) * dat[k+n-1];}
  
  //[a,b)の最小値を求める query(a,b,0,0,n)
  int query(int a,int b,int k=0,int l=0,int r=-1){
    if(r == -1) r = n, assert(a < n && b <= n);
    if(r<=a||b<=l)return INF;
    if(a<=l&&r<=b)return k == 0 && flag? -dat[k]:dat[k];
    int vl=query(a,b,k*2+1,l,(l+r)/2);
    int vr=query(a,b,k*2+2,(l+r)/2,r);
    int res = min(vl,vr);
    if(k == 0 && flag) res *= -1;
    return res;
  }

};


//rが小さい順に処理する。
RMQ initTo(const vector<T> &A){

  auto getDisT=[&](const T &a,const T &b){
    int x1,y1; tie(x1,y1,ignore,ignore) = a;
    int x2,y2; tie(x2,y2,ignore,ignore) = b;
    return abs(x1 - x2) + abs(y1 - y2);
  };
  auto getDis=[&](int i,int j){return getDisT(A[i],A[j]);};
  
  int n = A.size();
  RMQ res(n,1);
  vector<int> Idx(n);
  for(int i=0;i<n;i++) Idx[i] = i;

  sort(Idx.begin(),Idx.end(),[&](int a,int b){
      int r1 = get<2>(A[a]);
      int r2 = get<2>(A[b]);
      return r1 < r2;
    });
  
  RMQ mem(n,1);
  function<int(int,int)> search=[&](int pos,int start){
    const int r = get<2>(A[start]);
    if(getDis(start,pos) > r) return pos;
    if(pos + 1 >=n || getDis(start,pos+1) > r) return pos;
    int nx = mem.value(pos);
    if(nx == -INF || nx == pos) nx = pos+1;
    int to = search(nx,start);
    mem.update(pos,to);
    return to;
  };
  
  for(int i=0;i<n;i++) {
    int to=search(Idx[i],Idx[i]);
    res.update(Idx[i],to);
    mem.update(Idx[i],to);
  }
  return res;
}

int dfs(int pos,RMQ &To){
  int l = pos, r = To.value(pos);
  int to = To.query(l,r+1);
  if(to == pos) return pos;
  int res = dfs(to,To);
  To.update(pos,res);
  return res;
}

int dfs2(int pos,RMQ &To,RMQ &rTo,int n){
  int rpos = 2 * n - 1 - pos%n;
  int lmax = dfs(rpos,rTo) - rpos;
  int lto = dfs( To.query(max(0,pos - lmax),pos+1), To );
  int rto = dfs(pos,To);
  int to = max(lto,rto);
  if(lto > rto) to = dfs2(lto,To,rTo,n);
  To.update(pos,to);
  return to;
}

signed main(){
  int n;
  cin>>n;
  vector<T> A(n),rA;
  
  for(int i=0;i<n;i++){
    int x,y,r;
    scanf("%d%d%d",&x,&y,&r);
    A[i] = T(x,y,r,i);
  }

  sort(A.begin(),A.end(),[&](T &a,T &b){
      typedef complex<double> P;
      double x1,y1; tie(x1,y1,ignore,ignore) = a;
      double x2,y2; tie(x2,y2,ignore,ignore) = b;
      return arg(P(x1,y1)) < arg(P(x2,y2));
    });
  
  for(int i=0;i<2*n;i++) A.push_back(A[i%n]);
  rA = A; reverse(rA.begin(),rA.end());

  RMQ To = initTo(A);
  RMQ rTo = initTo(rA);
  
  vector<int> ans(n);
  int update = 1;
  while(update){
    update = 0;
    for(int i=n;i<2*n;i++){
      int ri = (2 * n - 1) - i%n;
      int idx = get<3>(A[i]);
      int to = dfs2(i,To,rTo,n);
      int rto = dfs2(ri,rTo,To,n);
      int num = to - i + 1;
      int rnum = rto - ri + 1;
      assert(A[i] == rA[ri]);
      int score = min(n,num+rnum-1);
      update |= ans[idx] < score;
      ans[idx] = score;
    }
  }    
  for(int a:ans) printf("%d\n",n - a);
  return 0;
}
accuracy: 1
time_ms: 1980
memory_kb: 67412
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
#define pr(...) GET_MACRO(__VA_ARGS__,pr5,pr4,pr3,pr2,pr1)(__VA_ARGS__)
#define pr1(a) (#a)<<"="<<(a)
#define pr2(a,b) pr1(a)<<", "<<pr1(b)
#define pr3(a,b,c) pr2(a,b)<<", "<<pr1(c)
#define pr4(a,b,c,d) pr3(a,b,c)<<", "<<pr1(d)
#define pr5(a,b,c,d,e) pr4(a,b,c,d)<<", "<<pr1(e)
//#define int long long
#define double long double
using namespace std;
const int N = 100010;
//const int INF = 1LL<<55;
const int INF = 1e9;
typedef pair<int,int> P;
typedef long long ll;
template<class T> T Max(T &a,T b){return a=max(a,b);}
template<class T> T Min(T &a,T b){return a=min(a,b);}
ostream& operator<<(ostream& o,P p){return o<<"("<<p.first<<","<<p.second<<")";}
istream& operator>>(istream& i,P &p){return i>>p.first>>p.second;}
typedef tuple<int,int,int,int> T; //x,y,r,idx;
ostream& operator<<(ostream& o,T &a){
  return o <<"( x="<<get<0>(a)<<", y="<<get<1>(a)<<", r="<<get<2>(a)<<", idx="<<get<3>(a)<<")";
}

class RMQ{
public:
  int INF = 1e9;
  int n;
  vector<int> dat;
  int flag; // Range Max Queryにしたいときはflag=1にする。
  
  //初期化
  RMQ(){n=-1;}
  RMQ(int n_,int flag = 0){
    this->flag = flag;
    n=1;
    while(n<n_)n*=2;
    dat.resize(2*n-1,INF);
  }
  
  //k番目の値をaに変更
  void update(int k,int a){
    assert(a >= 0);
    if(flag) a *= -1;
    k+=n-1;
    assert(dat[k] >= a);
    
    dat[k]=a;
    while(k>0){
      k=(k-1)/2;
      dat[k]=min(dat[k*2+1],dat[k*2+2]);
    }
  }

  int value(int k){return (flag?-1:1) * dat[k+n-1];}
  
  //[a,b)の最小値を求める query(a,b,0,0,n)
  int query(int a,int b,int k=0,int l=0,int r=-1){
    if(r == -1) r = n, assert(a < n && b <= n);
    if(r<=a||b<=l)return INF;
    if(a<=l&&r<=b)return k == 0 && flag? -dat[k]:dat[k];
    int vl=query(a,b,k*2+1,l,(l+r)/2);
    int vr=query(a,b,k*2+2,(l+r)/2,r);
    int res = min(vl,vr);
    if(k == 0 && flag) res *= -1;
    return res;
  }

};


//rが小さい順に処理する。
RMQ initTo(const vector<T> &A){

  auto getDisT=[&](const T &a,const T &b){
    int x1,y1; tie(x1,y1,ignore,ignore) = a;
    int x2,y2; tie(x2,y2,ignore,ignore) = b;
    return abs(x1 - x2) + abs(y1 - y2);
  };
  auto getDis=[&](int i,int j){return getDisT(A[i],A[j]);};
  
  int n = A.size();
  RMQ res(n,1);
  vector<int> Idx(n);
  for(int i=0;i<n;i++) Idx[i] = i;

  sort(Idx.begin(),Idx.end(),[&](int a,int b){
      int r1 = get<2>(A[a]);
      int r2 = get<2>(A[b]);
      return r1 < r2;
    });
  
  RMQ mem(n,1);
  function<int(int,int)> search=[&](int pos,int start){
    const int r = get<2>(A[start]);
    if(pos - start > 200000) return pos;
    if(getDis(start,pos) > r) return pos;
    if(pos + 1 >=n || getDis(start,pos+1) > r) return pos;
    int nx = mem.value(pos);
    if(nx == -INF || nx == pos) nx = pos+1;
    int to = search(nx,start);
    mem.update(pos,to);
    return to;
  };
  
  for(int i=0;i<n;i++) {
    int to=search(Idx[i],Idx[i]);
    res.update(Idx[i],to);
    mem.update(Idx[i],to);
  }
  return res;
}

int dfs(int pos,RMQ &To){
  int l = pos, r = To.value(pos);
  int to = To.query(l,r+1);
  if(to == pos) return pos;
  int res = dfs(to,To);
  To.update(pos,res);
  return res;
}

int dfs2(int pos,RMQ &To,RMQ &rTo,int n){
  int rpos = 2 * n - 1 - pos%n;
  int lmax = dfs(rpos,rTo) - rpos;
  int lto = dfs( To.query(max(0,pos - lmax),pos+1), To );
  int rto = dfs(pos,To);
  int to = max(lto,rto);
  if(lto > rto) to = dfs2(lto,To,rTo,n);
  To.update(pos,to);
  return to;
}

signed main(){
  int n;
  cin>>n;
  vector<T> A(n),rA;
  
  for(int i=0;i<n;i++){
    int x,y,r;
    scanf("%d%d%d",&x,&y,&r);
    A[i] = T(x,y,r,i);
  }

  sort(A.begin(),A.end(),[&](T &a,T &b){
      typedef complex<double> P;
      double x1,y1; tie(x1,y1,ignore,ignore) = a;
      double x2,y2; tie(x2,y2,ignore,ignore) = b;
      return arg(P(x1,y1)) < arg(P(x2,y2));
    });
  
  for(int i=0;i<2*n;i++) A.push_back(A[i%n]);
  rA = A; reverse(rA.begin(),rA.end());

  RMQ To = initTo(A);
  RMQ rTo = initTo(rA);
  
  vector<int> ans(n);
  int update = 1;
  while(update){
    update = 0;
    for(int i=n;i<2*n;i++){
      int ri = (2 * n - 1) - i%n;
      int idx = get<3>(A[i]);
      int to = dfs2(i,To,rTo,n);
      int rto = dfs2(ri,rTo,To,n);
      int num = to - i + 1;
      int rnum = rto - ri + 1;
      assert(A[i] == rA[ri]);
      int score = min(n,num+rnum-1);
      update |= ans[idx] < score;
      ans[idx] = score;
    }
  }    
  for(int a:ans) printf("%d\n",n - a);
  return 0;
}
accuracy: 1
time_ms: 2040
memory_kb: 58180
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define int long long

using Pi = pair<int, int>;

const int inf = 1LL<<55;

struct SegmentTree {
  vector<Pi> data;
  int sz;
  SegmentTree(int _sz) {
    sz = 1; while(sz < _sz) sz <<= 1;
    data.resize(2*sz-1);
  }
  void set(int k, Pi p) {
    k += sz-1;
    data[k] = p;
    while(k > 0) {
      k = (k-1)/2;
      data[k] = Pi(min(data[2*k+1].first, data[2*k+2].first),
		   max(data[2*k+1].second, data[2*k+2].second));
    }
  }
  Pi query(int a, int b, int k, int l, int r) {
    if(r <= a || b <= l) return Pi(inf, -inf);
    if(a <= l && r <= b) return data[k];
    Pi vl = query(a, b, 2*k+1, l, (l+r)/2);
    Pi vr = query(a, b, 2*k+2, (l+r)/2, r);
    return Pi(min(vl.first, vr.first),
	      max(vl.second, vr.second));
  }
  Pi query(int a, int b) {
    return query(a, b, 0, 0, sz);
  }
};

const int MAX_N = 200020;

int n;
int x[MAX_N], y[MAX_N], r[MAX_N];

int dist(int i, int j) {
  return llabs(x[i]-x[j])+llabs(y[i]-y[j]);
}

signed main() {
  cin >> n;
  for(int i = 0; i < n; ++i) {
    cin >> x[i] >> y[i] >> r[i];
  }
  vector<pair<double, int> > vec;
  const double PI = acos(-1);
  for(int i = 0; i < n; ++i) {
    double arg = atan2(y[i], x[i]);
    vec.emplace_back(arg, i);
    vec.emplace_back(arg+2*PI, i);
    vec.emplace_back(arg+4*PI, i);
  }
  sort(begin(vec), end(vec));
  vector<int> L(n), R(n);
  for(int i = n; i < 2*n; ++i) {
    double arg = vec[i].first;
    int idx = vec[i].second;
    //cout<<idx<<" "<<arg<<endl;
    {
      int fail = lower_bound(begin(vec), end(vec),
			     pair<double, int>(arg-PI, -1))-begin(vec)-1;
      int pass = i;
      //cout<<pass<<" "<<fail<<endl;
      while(fail+1 < pass) {
	int test = (fail+pass)/2;
	if(dist(idx, vec[test].second) <= r[idx]) pass = test;
	else fail = test;
      }
      L[i-n] = pass;
    }
    {
      int pass = i;
      int fail = lower_bound(begin(vec), end(vec),
			     pair<double, int>(arg+PI, -1))-begin(vec);
      //cout<<pass<<" "<<fail<<endl;
      while(pass+1 < fail) {
	int test = (pass+fail)/2;
	if(dist(idx, vec[test].second) <= r[idx]) pass = test;
	else fail = test;
      }
      R[i-n] = fail;
    }
    //cout<<idx<<" "<<L[i-n]<<" "<<R[i-n]<<endl;
  }
  SegmentTree seg(3*n);
  bool update = true;
  while(update) {
    update = false;
    for(int i = 0; i < 3*n; ++i) {
      int l = L[i%n], r = R[i%n];
      if(i < n) l -= n, r -= n;
      else if(i >= 2*n) l += n, r += n;
      seg.set(i, Pi(max(0ll, l), min(3*n, r)));
    }
    for(int i = n; i < 2*n; ++i) {
      Pi tmp = seg.query(L[i-n], R[i-n]);
      seg.set(i, Pi(tmp.first, tmp.second));
      if(L[i-n] != tmp.first || R[i-n] != tmp.second) update = true;
      L[i-n] = tmp.first;
      R[i-n] = tmp.second;
    }
  }
  vector<int> ans(n);
  for(int i = n; i < 2*n; ++i) {
    int idx = vec[i].second;
    ans[idx] = max(0ll, n-(R[i-n]-L[i-n]));
  }
  for(int i = 0; i < n; ++i) {
    cout << ans[i] << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 1080
memory_kb: 54560
final_rank: 1