LOJ6504 "Yali training 2018 Day5" Convex computational geometry, MO team

Portal


See off interval operation is still considering Mo team, then you can find: For our collection of original convex hull maintain a linked list in accordance with the polar angle sequence, then delete a location can \ (O (1) \) , delete the withdrawal operations can also \ ( O (. 1) \) (because the original structure of the current node on the list is recorded before its successor precursor), but the dynamic addition of at least a two operating points \ (log \) complexity. So we want to avoid as much as possible to join dynamic.

Because the team so I never learned to roll back Mo wording is rather strange: Let \ (solve (l, r) \) represents the point being addressed in the left block (l \) \ in the right end point of the block (\ r) \ within inquiry, and at this time the blocks have been maintained \ (L \) left point to block \ (R & lt \) the convex hull of the right end of the list points and maintain the answer.

At this point in the block for the left (L \) \ the right end point of the block (R & lt \) \ interrogation in, we only need to loose part can be subtracted to get the answer, then the stack undo a deletion sequence.

Upon inquiry done by removing the element into the recursive \ (solve (l + 1, r) \) and \ (Solve (L, R & lt-. 1) \) . I remember repeating \ (solve \) steps do not do many times.

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

int read(){
    int a = 0; char c = getchar(); bool f = 0;
    while(!isdigit(c)){f = c == '-'; c = getchar();}
    while(isdigit(c)){
        a = a * 10 + c - 48; c = getchar();
    }
    return f ? -a : a;
}

#define int long long
const int _ = 1.5e5 + 7 , T = sqrt(_) + 10;
struct node{int P , S;}now[_]; struct query{int l , r , id;};
#define PII pair < int , int >
int N , M , id[_] , ans[_] , S; vector < query > qry[T][T];
PII pos[_]; long double ang[_]; bool vis[T][T];

int operator %(PII A , PII B){return A.first * B.second - A.second * B.first;}
int cnt = 0;

void del(int x){
    ++cnt;
    S = S - pos[x] % pos[now[x].S] - pos[now[x].P] % pos[x] + pos[now[x].P] % pos[now[x].S];
    now[now[x].P].S = now[x].S; now[now[x].S].P = now[x].P;
}

void add(int x){
    ++cnt;
    S = S - pos[now[x].P] % pos[now[x].S] + pos[now[x].P] % pos[x] + pos[x] % pos[now[x].S];
    now[now[x].P].S = x; now[now[x].S].P = x;
}

void solve(int l , int r){
    //cerr << l << ' ' << r << endl;
    if(vis[l / T][r / T]) return;
    vis[l / T][r / T] = 1;
    for(auto t : qry[l / T][r / T]){
        assert(t.l - l <= T && r - t.r <= T);
        for(int i = l ; i < t.l ; ++i) del(i);
        for(int i = r ; i > t.r ; --i) del(i);
        ans[t.id] = S;
        for(int i = t.r + 1 ; i <= r ; ++i) add(i);
        for(int i = t.l - 1 ; i >= l ; --i) add(i);
    }

    if(r - l > T){
        int cur = l; do{del(l++);}while(l % T); solve(l , r); do{add(--l);}while(l != cur);
        cur = r; do{del(r--);}while((r + 1) % T); solve(l , r); do{add(++r);}while(r != cur);
    }
}

signed main(){
    N = read(); M = read();
    for(int i = 0 ; i < N ; ++i){
        pos[i].first = read(); pos[i].second = read();
        id[i] = i; ang[i] = atan2(pos[i].second , pos[i].first);
    }
    sort(id , id + N , [&](int x , int y){return ang[x] < ang[y];});
    for(int i = 0 ; i < N ; ++i){now[id[i]].P = id[i ? i - 1 : N - 1]; now[id[i]].S = id[i == N - 1 ? 0 : i + 1];}
    for(int i = 1 ; i <= M ; ++i){int p = read() - 1 , q = read() - 1; qry[p / T][q / T].push_back((query){p , q , i});}
    for(int i = 0 ; i < N ; ++i){S += pos[i] % pos[now[i].S];}
    solve(0 , N - 1); for(int i = 1 ; i <= M ; ++i) printf("%lld\n" , ans[i]);
    cerr << cnt << endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/Itst/p/11520660.html