LOJ刷题记录:SHOI2016(2036-2041)

来源:互联网 发布:剑灵n卡优化设置2017 编辑:程序博客网 时间:2024/06/09 16:26

LOJ刷题记录:SHOI2016(2036-2041)


loj#2036. 「SHOI2015」自动刷题机

直接二分就好了。

#include <bits/stdc++.h>using namespace std;const int MAXN = 200005;int x[MAXN];int n, k;int calc(long long N){    long long ans = 0;    int cnt = 0;    for (int i = 1; i <= n; i++) {        // cerr << x[i] << " ";        ans += x[i];        if (ans < 0) ans = 0;        if (ans >= N) cnt++, ans = 0;    }    // cerr << endl;    return cnt;}int main(){    scanf("%d%d", &n, &k);    for (int i = 1; i <= n; i++) scanf("%d", &x[i]);    long long L = 1, R = 1e18, mid;    while (L <= R) {        mid = L+((R-L)>>1);        if (calc(mid) <= k) R = mid-1;        else L = mid+1;    }    long long Low = R+1;    L = 1, R = 1e18;    while (L <= R) {        mid = L+((R-L)>>1);        if (calc(mid) >= k) L = mid+1;        else R = mid-1;    }    long long Up = L-1;    // cerr << calc(Up) << endl;    if (calc(Up) != k || calc(Low) != k || Low > Up) puts("-1");    else cout << Low << " " << Up << endl;    return 0;}

loj#2037. 「SHOI2015」脑洞治疗仪

以前做过…

#include <bits/stdc++.h>using namespace std;const int MAXN = 200005;int dat[MAXN*4], lc[MAXN*4], rc[MAXN*4], l[MAXN*4], r[MAXN*4];int change[MAXN*4], llen[MAXN*4], rlen[MAXN*4], len[MAXN*4], top = 0, root = 0;inline int new_node(int opl, int opr){ return ++top, l[top] = opl, r[top] = opr, top; }inline void pdw(int nd) // 1 nh / -1 hole{    if (!change[nd]) return;    change[lc[nd]] = change[rc[nd]] = change[nd]*(lc[nd]!=0);    dat[nd] = (r[nd]-l[nd]+1)*(change[nd]==1);    llen[nd] = rlen[nd] = len[nd] = (r[nd]-l[nd]+1)*(change[nd]==-1);    change[nd] = 0;}inline void update(int nd){    pdw(nd), pdw(lc[nd]), pdw(rc[nd]);    if (l[nd] == r[nd]) {        llen[nd] = rlen[nd] = len[nd] = (dat[nd]==0);        return;    }    llen[nd] = llen[lc[nd]]+(dat[lc[nd]] == 0)*llen[rc[nd]];    rlen[nd] = rlen[rc[nd]]+(dat[rc[nd]] == 0)*rlen[lc[nd]];    len[nd] = max(max(len[lc[nd]], len[rc[nd]]), rlen[lc[nd]]+llen[rc[nd]]);    dat[nd] = dat[lc[nd]]+dat[rc[nd]];}int pat[MAXN];void build(int &nd, int l, int r){    nd = new_node(l, r);    if (l == r) dat[nd] = pat[r];    else build(lc[nd], l, (l+r)/2), build(rc[nd], (l+r)/2+1, r);    update(nd);}void modify(int nd, int opl, int opr, int alc){    if (opl > opr) return;    pdw(nd);    if (opl == l[nd] && opr == r[nd]) change[nd] = alc, pdw(nd);    else {        int mid = (l[nd]+r[nd])/2;        if (opr <= mid) modify(lc[nd], opl, opr, alc);        else if (opl > mid) modify(rc[nd], opl, opr, alc);        else modify(lc[nd], opl, mid, alc), modify(rc[nd], mid+1, opr, alc);        pdw(lc[nd]), pdw(rc[nd]), update(nd);    }}int query(int nd, int opl, int opr){    pdw(nd);    if (opl == l[nd] && opr == r[nd]) return len[nd];    else {        int mid = (l[nd]+r[nd])/2;        pdw(lc[nd]), pdw(rc[nd]);        if (opr <= mid) return query(lc[nd], opl, opr);        else if (opl > mid) return query(rc[nd], opl, opr);        else return max(max(query(lc[nd], opl, mid), query(rc[nd], mid+1, opr)),                 min(rlen[lc[nd]], mid-opl+1)+min(llen[rc[nd]], opr-mid));    }}void dfs(int nd, int tab = 0){    if (!nd) return;    for (int i = 1; i <= tab; i++) putchar(' ');    printf("[%d, %d], dat = %d, llen = %d, rlen = %d, len = %d, change = %d\n", l[nd], r[nd], dat[nd], llen[nd], rlen[nd], len[nd], change[nd]);    dfs(lc[nd], tab+2), dfs(rc[nd], tab+2);}int query_sum(int nd, int opl, int opr){    if (opl > opr) return 0;    pdw(nd);    int mid = (l[nd]+r[nd])/2;    if (opl == l[nd] && opr == r[nd]) return dat[nd];    else return query_sum(lc[nd], opl, min(opr, mid))+query_sum(rc[nd], max(opl, mid+1), opr);}int last_pos(int nd, int k) // in node nd, the first place to have k holes{    if (l[nd] == r[nd]) return l[nd];    pdw(nd), pdw(lc[nd]), pdw(rc[nd]);    int lp = r[lc[nd]]-l[lc[nd]]+1-dat[lc[nd]];    // cerr << l[nd] << "," << r[nd] << " ; " << k << " ; " << lp << endl;    if (lp >= k) return last_pos(lc[nd], k);    else return last_pos(rc[nd], k-lp);}void fix(int ll, int lr, int nl, int nr){    int dt = query_sum(root, ll, lr);    // cerr << "-->" << max(0, nl-1)-query_sum(root, 1, nl-1)+dt << "-" << k << endl;    modify(root, ll, lr, -1);    if (dt == 0) return;    int k = last_pos(root, nl-1-query_sum(root, 1, nl-1)+dt);    modify(root, nl, min(nr, k), 1);}inline int read(){    int a = 0, c;    do c = getchar(); while (!isdigit(c));    while (isdigit(c))        a = a*10+c-'0', c = getchar();    return a;}int n, m;int main(){    n = read(), m = read();    for (int i = 1; i <= n; i++) pat[i] = 1;    build(root, 1, n);    for (int i = 1; i <= m; i++) {        // dfs(root);        int tp, l, r, u, v;        tp = read();        if (tp == 0) l = read(), r = read(), modify(root, l, r, -1);        else if (tp == 1) l = read(), r = read(), u = read(), v = read(), fix(l, r, u, v);        else l = read(), r = read(), printf("%d\n", query(root, l, r));        // for (int j = 1; j <= n; j++) cerr<<query_sum(root, j, j)<<" ";        // cerr << endl;        // dfs(root);    }    return 0;}

loj#2038. 「SHOI2015」超能粒子炮・改

S(n,k)=0ik(ni) mod 2333=0ik(nmod2333imod2333)(n/2333i/2333)

考虑i mod 2333必然成周期性,在每一个周期中i/2333又恰好都相等,考虑分块处理,第一部分是完整的块,也就是mod 23330..2332的部分,为:

P=k+12333,Q=(k+1) mod 23330i<PS(n mod 2333,2332)(n/2333i)=S(n mod 2333,2332)×S(n/2333,P1)

第二部分为余下的部分,也就是:

0i<Q(nmod2333imod2333)(n/2333k/2333)=S(n mod 2333,Q1)(n/2333k/2333)

这样两部分加起来美滋滋,复杂度O(log22333(n))

#include <bits/stdc++.h>using namespace std;const int mod = 2333;int c[mod+20][mod+20], f[mod+20][mod+20];inline int lucas(long long i, long long j){    if (i < mod && j < mod) return c[i][j];    return c[i%mod][j%mod]*lucas(i/mod, j/mod)%mod;}inline int fun(long long i, long long j){    if (i < mod && j < mod) return f[i][j];    return (f[i%mod][mod-1]*fun(i/mod, (j+1)/mod-1)+lucas(i/mod, j/mod)*f[i%mod][(j+1)%mod-1])%mod;}int main(){    c[0][0] = 1;    for (int i = 1; i < mod; i++)        for (register int j = 0; j <= i; j++)            c[i][j] = (c[i-1][j]+(j>=1)*c[i-1][j-1])%mod;    for (int i = 0; i < mod; i++) {        f[i][0] = 1;        for (register int j = 1; j < mod; j++)            f[i][j] = (f[i][j-1]+c[i][j])%mod;    }    // cerr << lucas(12132, 3211) << endl;    int T; scanf("%d", &T);    while (T--) {        long long n, m;        scanf("%lld%lld", &n, &m);        printf("%d\n", fun(n, m));    }    return 0;}

loj#2039. 「SHOI2015」激光发生器

写了一天的码农计算几何题…

这种题呀…大概是有毒

#include <bits/stdc++.h>using namespace std;const int MAXN = 105;const double eps = 1e-9;struct point {    double x, y;    friend point operator + (const  point &a, const point &b)    { return (point){a.x+b.x, a.y+b.y}; }    friend point operator - (const point &a, const point &b)    { return (point){a.x-b.x, a.y-b.y}; }    friend point operator * (double lambda, const point &a)    { return (point){lambda*a.x, lambda*a.y}; }    friend double operator * (const point &a, const point &b)    { return a.x*b.y-a.y*b.x; }    inline double len() const    { return sqrt(x*x+y*y); }    inline double dot(const point &a)    { return x*a.x+y*a.y; }    double angel(const point &a)    { return acos((x*a.x+y*a.y)/len()/a.len()); }    point rot(double theta)    { return (point){cos(theta)*x-sin(theta)*y, sin(theta)*x+cos(theta)*y}; }};typedef point vec;struct line {    point p;    vec v;    inline line normal_left(const point &a)    { return (line){a, v.rot(M_PI/2)}; }    inline line normal_right(const point &a)    { return (line){a, v.rot(-M_PI/2)}; }    inline bool on_left(const point &a)    { return v*(a-p) > 0; }    inline bool on_right(const point &a)    { return !on_left(a); }    friend point operator * (const line &a, const line &b)    {        double lambda = b.v*(b.p-a.p)/(b.v*a.v);        // cerr << " " << lambda << endl;        return a.p+lambda*a.v;    }    bool along(const point &pt)    {        return (pt-p).dot(v) > eps;    }    inline bool on_line(const point &a)    {        return (a-p).dot(a-(p+v)) <= eps;    }} px;int n;double lambda[MAXN];line ln[MAXN];int main(){    double a, b, c, d, x, y;    scanf("%lf%lf%lf%lf", &a, &b, &c, &d);    px.p = (point){a, b}, px.v = (vec){c, d};    scanf("%d", &n);    for (int i = 1; i <= n; i++) {        scanf("%lf%lf%lf%lf%lf%lf", &a, &b, &c, &d, &x, &y);        ln[i].p = (point){a, b}, ln[i].v = (point){c-a, d-b}, lambda[i] = x/y;    }    bool pp = 0;    for (int i = 1; i <= 10; i++) {        point fc;        double len = 1e30;        int id;        for (int j = 1; j <= n; j++) {            point pt = px*ln[j];            if (ln[j].on_line(pt) && px.along(pt)) {                if ((pt-px.p).len() < len)                    fc = pt, len = (pt-px.p).len(), id = j;            }        }        if (len >= 1e30) break;        line nor = ln[id].on_left(px.p)?ln[id].normal_left(fc):ln[id].normal_right(fc);        double ang = (px.p-fc).angel(nor.v);        if ((px.p-fc)*nor.v < 0) ang = -ang;        ang = ang+ang*lambda[id];        px = (line){fc, (px.p-fc).rot(ang)};        pp = 1;        // cerr << fc.x << " " << fc.y << "," << px.v.x << " " << px.v.y << endl;        printf("%d ", id);    }    if (pp == 0) puts("NONE");    else puts("");    return 0;}

loj#2040. 「SHOI2015」零件组装机

以前做过…如果有方案,方案唯一,直接找就好了…

#include <bits/stdc++.h>using namespace std;const int MAXN = 100005;inline int gcd(int a, int b){ return b==0?a:gcd(b, a%b); }vector<int> vec[MAXN];int n, T, m;bool solve(int L, int R){    if (L == R) return 1;    if (L > R || vec[L].empty()) return 0;    // if (vec[L].size() == R-L) return solve(L+1, R);    int d = vec[L][vec[L].size()-1]-L, plc = -1, cnt = 0;    for (int i = vec[L].size()-1; i >= 0; i--) {        int tar = vec[L][i]; cnt++;        if (gcd(tar-L, d) == tar-L && (R-L)/(tar-L) == cnt && R-tar+1 >= tar-L) {            plc = tar;            break;        }    }    if (plc == -1) return 0;    // cerr << L << " " << R << " " << plc << endl;    for (int i = L; i < plc; i++) {        int N = (R-i)/(plc-L);        while (N) {            if (vec[i][vec[i].size()-1] != i+(plc-L)*N) return 0;            N--, vec[i].pop_back();        }     }    return solve(L, plc-1)&&solve(plc, R);}unordered_set<int> st[MAXN];int main(){    scanf("%d", &T);    while (T--) {        scanf("%d%d", &n, &m);        for (int i = 0; i < n; i++) vec[i].clear();        int flag = 0;        for (int i = 0; i < n; i++) st[i].clear();        for (int i = 1; i <= m; i++) {            int u, v;            scanf("%d%d", &u, &v);            if (u == v) { flag = 1;  }            if (u > v) swap(u,v);            if (!st[u].count(v)) {                st[u].insert(v);                vec[u].push_back(v);            } else flag = 1;        }        if (flag) { puts("NO"); continue; }        for (int i = 0; i < n; i++)            sort(vec[i].begin(), vec[i].end());        if (solve(0, n-1)) puts("YES");        else puts("NO");    }    return 0;}
原创粉丝点击