提交记录 32302


用户 题目 状态 得分 用时 内存 语言 代码长度
saffah_dsh_260814 noi17f. 【NOI2017】分身术 Time Limit Exceeded 25 3 s 41432 KB C++17 6.88 KB
提交时间 评测时间
2026-08-14 10:40:04 2026-08-14 10:42:25
// NOI2017 分身术 - segment tree of convex hulls + O(log) tangent bridge merge.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

static const int MAXN = 100005;

static ll PX[MAXN], PY[MAXN]; // points sorted by (x,y)

static inline ll crs2(ll ax, ll ay, ll bx, ll by) { return ax*by - ay*bx; }
static inline ll crs3(int a, int b, int c) {
    return (PX[b]-PX[a])*(PY[c]-PY[b]) - (PY[b]-PY[a])*(PX[c]-PX[b]);
}

static vector<int> lo[4*MAXN], up[4*MAXN];

// ---- build merges (linear) ----
static void merge_lo(const vector<int>& A, const vector<int>& B, vector<int>& out) {
    out = A;
    for (int p : B) {
        while (out.size() >= 2 && crs3(out[out.size()-2], out.back(), p) <= 0) out.pop_back();
        out.push_back(p);
    }
}
static void merge_up(const vector<int>& A, const vector<int>& B, vector<int>& out) {
    out = A;
    for (int p : B) {
        while (out.size() >= 2 && crs3(out[out.size()-2], out.back(), p) >= 0) out.pop_back();
        out.push_back(p);
    }
}

void build(int node, int l, int r) {
    if (r - l == 1) { lo[node].push_back(l); up[node].push_back(l); return; }
    int mid = (l+r)/2;
    build(2*node, l, mid);
    build(2*node+1, mid, r);
    merge_lo(lo[2*node], lo[2*node+1], lo[node]);
    merge_up(up[2*node], up[2*node+1], up[node]);
}

// ---- O(log) tangent bridge ----
// smallest j in [0,q-1] with (j==q-1 || crs3(ai,B[j],B[j+1]) < 0)
static inline int upper_tangent_j(int ai, const vector<int>& B) {
    int q = (int)B.size();
    if (q == 1) return 0;
    int l = 0, r = q-1, ans = q-1;
    while (l <= r) {
        int mid = (l+r)>>1;
        if (mid == q-1 || crs3(ai, B[mid], B[mid+1]) < 0) { ans = mid; r = mid-1; }
        else l = mid+1;
    }
    return ans;
}
// smallest j with (j==q-1 || crs3(ai,B[j],B[j+1]) > 0)
static inline int lower_tangent_j(int ai, const vector<int>& B) {
    int q = (int)B.size();
    if (q == 1) return 0;
    int l = 0, r = q-1, ans = q-1;
    while (l <= r) {
        int mid = (l+r)>>1;
        if (mid == q-1 || crs3(ai, B[mid], B[mid+1]) > 0) { ans = mid; r = mid-1; }
        else l = mid+1;
    }
    return ans;
}

static void merge_up_bridge(const vector<int>& A, const vector<int>& B, vector<int>& out) {
    if (A.empty()) { out = B; return; }
    if (B.empty()) { out = A; return; }
    int p = (int)A.size(), q = (int)B.size();
    int l = 0, r = p-1, ans = 0;
    while (l <= r) {
        int mid = (l+r)>>1;
        int j = upper_tangent_j(A[mid], B);
        bool ok = (mid == 0) || (crs3(A[mid-1], A[mid], B[j]) < 0);
        if (ok) { ans = mid; l = mid+1; } else r = mid-1;
    }
    int i = ans, j = upper_tangent_j(A[i], B);
    out.clear();
    out.reserve(i+1 + (q-j));
    for (int k = 0; k <= i; k++) out.push_back(A[k]);
    out.push_back(B[j]);
    for (int k = j+1; k < q; k++) out.push_back(B[k]);
}

static void merge_lo_bridge(const vector<int>& A, const vector<int>& B, vector<int>& out) {
    if (A.empty()) { out = B; return; }
    if (B.empty()) { out = A; return; }
    int p = (int)A.size(), q = (int)B.size();
    int l = 0, r = p-1, ans = 0;
    while (l <= r) {
        int mid = (l+r)>>1;
        int j = lower_tangent_j(A[mid], B);
        bool ok = (mid == 0) || (crs3(A[mid-1], A[mid], B[j]) > 0);
        if (ok) { ans = mid; l = mid+1; } else r = mid-1;
    }
    int i = ans, j = lower_tangent_j(A[i], B);
    out.clear();
    out.reserve(i+1 + (q-j));
    for (int k = 0; k <= i; k++) out.push_back(A[k]);
    out.push_back(B[j]);
    for (int k = j+1; k < q; k++) out.push_back(B[k]);
}

struct Hull { vector<int> lo, up; };

Hull query(int node, int l, int r, const vector<int>& dels) {
    auto it = lower_bound(dels.begin(), dels.end(), l);
    if (it == dels.end() || *it >= r) {
        Hull h; h.lo = lo[node]; h.up = up[node];
        return h;
    }
    if (r - l == 1) return Hull{};
    int mid = (l+r)/2;
    Hull L = query(2*node, l, mid, dels);
    Hull R = query(2*node+1, mid, r, dels);
    Hull res;
    if (L.lo.empty()) res.lo = move(R.lo);
    else if (R.lo.empty()) res.lo = move(L.lo);
    else merge_lo_bridge(L.lo, R.lo, res.lo);
    if (L.up.empty()) res.up = move(R.up);
    else if (R.up.empty()) res.up = move(L.up);
    else merge_up_bridge(L.up, R.up, res.up);
    return res;
}

// fast int reader
static char inbuf[1<<22]; static size_t inpos=0, inlen=0;
static inline char gc() { if (inpos>=inlen) { inlen = fread(inbuf,1,sizeof(inbuf),stdin); inpos=0; if(inlen==0) return 0; } return inbuf[inpos++]; }
static inline ll rd() {
    char c; while ((c=gc()) && (c<'0'||c>'9') && c!='-') ;
    if (c==0) return 0;
    int sgn=1; if (c=='-'){ sgn=-1; c=gc(); }
    ll v=0; while (c>='0'&&c<='9'){ v=v*10+(c-'0'); c=gc(); }
    return sgn*v;
}

static char outbuf[1<<22]; static size_t outpos=0;
static inline void wl(ll v) {
    if (outpos > (1<<22) - 64) { fwrite(outbuf,1,outpos,stdout); outpos=0; }
    if (v==0) { outbuf[outpos++]='0'; outbuf[outpos++]='\n'; return; }
    char tmp[32]; int t=0;
    if (v<0){ outbuf[outpos++]='-'; v=-v; }
    while (v){ tmp[t++] = '0'+(v%10); v/=10; }
    while (t) outbuf[outpos++] = tmp[--t];
    outbuf[outpos++]='\n';
}

int main() {
    int n = (int)rd();
    int m = (int)rd();
    struct Pt { ll x,y; int id; };
    static Pt ps[MAXN];
    for (int i=0;i<n;i++){ ps[i].x=rd(); ps[i].y=rd(); ps[i].id=i; }
    sort(ps, ps+n, [](const Pt&a, const Pt&b){ return a.x!=b.x ? a.x<b.x : a.y<b.y; });
    for (int i=0;i<n;i++){ PX[i]=ps[i].x; PY[i]=ps[i].y; }
    static int pos[MAXN];
    for (int i=0;i<n;i++) pos[ps[i].id] = i;

    {
        function<void(int,int,int)> b = [&](int node,int l,int r){
            if (r-l==1){ lo[node].push_back(l); up[node].push_back(l); return; }
            int mid=(l+r)/2; b(2*node,l,mid); b(2*node+1,mid,r);
            merge_lo(lo[2*node],lo[2*node+1],lo[node]);
            merge_up(up[2*node],up[2*node+1],up[node]);
        };
        b(1,0,n);
    }

    ll S = -1;
    static int dels[MAXN];
    vector<int> dv; dv.reserve(110);
    static int hullbuf[MAXN];
    for (int q=0;q<m;q++){
        int k = (int)rd();
        int cnt=0;
        for (int j=0;j<k;j++){
            ll c = rd();
            ll v = S + c;
            v %= n; if (v<0) v += n;
            int p = (int)v;
            dels[cnt++] = pos[p];
        }
        sort(dels, dels+cnt);
        int c2=0;
        for (int j=0;j<cnt;j++){ if (j==0 || dels[j]!=dels[j-1]) dels[c2++]=dels[j]; }
        cnt=c2;
        dv.assign(dels, dels+cnt);

        Hull h = query(1, 0, n, dv);
        ll area = 0;
        int hz = 0;
        for (int p : h.lo) hullbuf[hz++] = p;
        for (int i=(int)h.up.size()-2; i>=1; i--) hullbuf[hz++] = h.up[i];
        if (hz >= 3) {
            ll s2 = 0;
            for (int i=0;i<hz;i++){
                int a=hullbuf[i], b=hullbuf[(i+1)%hz];
                s2 += PX[a]*PY[b] - PY[a]*PX[b];
            }
            if (s2<0) s2=-s2;
            area = s2;
        }
        S = area;
        wl(area);
    }
    fwrite(outbuf,1,outpos,stdout);
    return 0;
}

CompilationN/AN/ACompile OKScore: N/A

Testcase #13.271 ms18 MB + 392 KBAcceptedScore: 5

Testcase #220.454 ms18 MB + 680 KBAcceptedScore: 5

Testcase #320.338 ms18 MB + 680 KBAcceptedScore: 5

Testcase #420.296 ms18 MB + 680 KBAcceptedScore: 5

Testcase #53 s30 MB + 152 KBTime Limit ExceededScore: 0

Testcase #63 s32 MB + 116 KBTime Limit ExceededScore: 0

Testcase #73 s32 MB + 116 KBTime Limit ExceededScore: 0

Testcase #83 s34 MB + 72 KBTime Limit ExceededScore: 0

Testcase #93 s30 MB + 116 KBTime Limit ExceededScore: 0

Testcase #103 s31 MB + 864 KBTime Limit ExceededScore: 0

Testcase #113 s30 MB + 668 KBTime Limit ExceededScore: 0

Testcase #121.794 s33 MB + 448 KBAcceptedScore: 5

Testcase #133 s33 MB + 696 KBTime Limit ExceededScore: 0

Testcase #143 s34 MB + 216 KBTime Limit ExceededScore: 0

Testcase #153 s40 MB + 472 KBTime Limit ExceededScore: 0

Testcase #163 s36 MB + 968 KBTime Limit ExceededScore: 0

Testcase #173 s37 MB + 788 KBTime Limit ExceededScore: 0

Testcase #183 s38 MB + 592 KBTime Limit ExceededScore: 0

Testcase #193 s39 MB + 444 KBTime Limit ExceededScore: 0

Testcase #203 s40 MB + 200 KBTime Limit ExceededScore: 0


Judge Duck Online | 评测鸭在线
Server Time: 2026-09-11 23:57:40 | Loaded in 1 ms | Server Status
个人娱乐项目,仅供学习交流使用 | 捐赠