• Gym 101482 题解


    B:Biking Duck

    题意:现在有一个人要从(x1,y1)点走到(x2,y2)点, 现在走路的速度为v。 还有骑自行车的速度v2,自行车要从某个自行车站到另一个自行车站,现在我们可以视地图的边界都为自行车站,求最小时间是多少。

    题解:对于忽视边界的问题,那就是暴力枚举。现在有了边界, 我们假设一个点在边界,那么我们可以枚举另一个自行车点之后,在某个边界上三分另一个点。 下一个情况就是2个自行车站都在边界上,我们三分套三分去维护找到最小值。

    思维不怎么麻烦,就是写的有点麻烦。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<double,double> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    pll p[N], x, y, ld, ru;
    double v1, v2;
    int n;
    double dis(pll p1, pll p2){
        return sqrt(pow(p1.fi-p2.fi,2)+pow(p1.se-p2.se,2));
    }
    double cal(pll p1, pll p2, int fx){
        if(fx == 1 || fx == 3){
            double posy;
            if(fx == 1) posy = ld.se;
            else posy = ru.se;
            double lx = ld.fi, rx = ru.fi;
            for(int i = 0; i < 60; ++i){
                double m = (lx+rx)/2.0;
                double mm = (m+rx)/2.0;
                if((dis(p1,{m,posy})/v2+dis(p2,{m,posy})/v1) > (dis(p1,{mm,posy})/v2+dis(p2,{mm,posy})/v1)) lx = m;
                else rx = mm;
            }
            return dis(p1,{lx,posy})/v2 + dis(p2,{lx,posy})/v1;
        }
        else {
            double posx;
            if(fx == 2) posx = ld.fi;
            else posx = ru.fi;
            double ly = ld.se, ry = ru.se;
            for(int i = 0; i < 60; ++i){
                double m = (ly+ry)/2.0;
                double mm = (m+ry)/2.0;
                if(dis(p1,{posx,m})/v2 + dis(p2,{posx,m})/v1 > dis(p1,{posx,mm})/v2 + dis(p2,{posx,mm})/v1) ly = m;
                else ry = mm;
            }
            return dis(p1,{posx,ly})/v2 + dis(p2,{posx,ly})/v1;
        }
    }
    double solve(int fx, int ffx){
        if(fx == 1 || fx == 3){
            double posy;
            if(fx == 1) posy = ld.se;
            else posy = ru.se;
            double lx = ld.fi, rx = ru.fi;
            for(int i = 0; i < 60; ++i){
                double m = (lx+rx)/2.0;
                double mm = (m+rx)/2.0;
                if(dis(x,{m,posy})/v1+cal({m,posy},y,ffx) > dis(x,{mm,posy})/v1+cal({mm,posy},y,ffx)) lx = m;
                else rx = mm;
            }
    
            return dis(x,{lx,posy})/v1+cal({lx,posy},y,ffx);
        }
        else {
            double posx;
            if(fx == 2) posx = ld.fi;
            else posx = ru.fi;
            double ly = ld.se, ry = ru.se;
            for(int i = 0; i < 60; ++i){
                double m = (ly+ry)/2.0;
                double mm = (m+ry)/2.0;
                if(dis(x,{posx,m})/v1+cal({posx,m},y,ffx) > dis(x,{posx,mm})/v1+cal({posx,mm},y,ffx)) ly = m;
                else ry = mm;
            }
            return dis(x,{posx,ly})/v1+cal({posx,ly},y,ffx);
        }
    }
    int main(){
        scanf("%lf%lf", &v1, &v2);
        scanf("%lf%lf", &ld.fi, &ld.se);
        scanf("%lf%lf", &ru.fi, &ru.se);
        scanf("%lf%lf", &x.fi, &x.se);
        scanf("%lf%lf", &y.fi, &y.se);
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
            scanf("%lf%lf", &p[i].fi, &p[i].se);
        double ans = dis(x,y)/v1;
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j){
                double tmp = dis(p[i],p[j])/v2+(dis(p[i],x)+dis(p[j],y))/v1;
                ans = min(ans, tmp);
            }
        for(int i = 1; i <= n; ++i){
            ans = min(ans, dis(x,p[i])/v1+cal(p[i],y,1));
            ans = min(ans, dis(x,p[i])/v1+cal(p[i],y,2));
            ans = min(ans, dis(x,p[i])/v1+cal(p[i],y,3));
            ans = min(ans, dis(x,p[i])/v1+cal(p[i],y,4));
    
            ans = min(ans, dis(y,p[i])/v1+cal(p[i],x,1));
            ans = min(ans, dis(y,p[i])/v1+cal(p[i],x,2));
            ans = min(ans, dis(y,p[i])/v1+cal(p[i],x,3));
            ans = min(ans, dis(y,p[i])/v1+cal(p[i],x,4));
        }
        for(int i = 1; i <= 4; ++i){
            for(int j = 1; j <= 4; ++j){
                ans = min(ans, solve(i,j));
            }
        }
        printf("%.10f
    ", ans);
        return 0;
    }
    View Code

    C:Cent Savings

    题意:将传送带上的物品最多分成m+1个部分,每部分单独付费这个付费是四舍五入,然后问最小花费是多少。

    题解: DP跑一下花费。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 2e3 + 100;
    int a[N], b[N];
    int dp[N][200];
    int main(){
        int n, m;
        int ans = 0;
        memset(dp, inf, sizeof(dp));
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i){
            scanf("%d", &a[i]);
            ans += a[i] / 10;
            a[i] %= 10;
            b[i] = b[i-1] + a[i];
        }
        ans *= 10;
        dp[0][0] = 0;
        for(int i = 1; i <= n; ++i){
            for(int l = 1; l <= i; ++l){
                int sum = b[i] - b[l-1];
                int t = sum % 10;
                if(t > 4) sum = sum + 10 - t;
                else sum -= t;
                for(int k = 0; k <= m; ++k)
                    dp[i][k+1] = min(dp[i][k+1], sum + dp[l-1][k]);
            }
        }
        int fans = inf;
        for(int i = 0; i <= m+1; ++i){
            fans = min(fans, dp[n][i]);
        }
        cout << ans+fans << endl;
        return 0;
    }
    View Code

    D:Digi Comp II

    题意:现在有N个板子,每个板子都有一个朝向,每次一个求落在板子上,求会掉到现在的方向的这一边,然后板子换一个方向,现在落下n个球,问最后所有板子的方向。

    题解:模拟, 按照toposort的方式处理就好了。  注意就是左边和右边都有可能是指向同一个新的板子。

    所以不能先把所有板子都 --度数之后,再入队。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 5e5 + 100;
    LL a[N]; LL n;
    int vis[N], m, d[N];
    int to[N][2];
    void toposort(){
        queue<int> q;
        for(int i = 1; i <= m; ++i){
            if(!d[i]) q.push(i);
        }
        while(!q.empty()){
            int x = q.front();
            q.pop();
            a[to[x][0]] += a[x]/2;
            a[to[x][1]] += a[x]/2;
            if(a[x]&1){
                a[to[x][vis[x]]]++;
                vis[x] ^= 1;
            }
            --d[to[x][0]];
            if(d[to[x][0]] == 0) q.push(to[x][0]);
            --d[to[x][1]];
            if(d[to[x][1]] == 0) q.push(to[x][1]);
        }
    }
    int main(){
        scanf("%lld%d", &n, &m);
        char op[3];
        for(int i = 1; i <= m; ++i){
            scanf("%s", op);
            if(op[0] == 'L') vis[i] = 0;
            else vis[i] = 1;
            scanf("%d%d", &to[i][0], &to[i][1]);
            ++d[to[i][0]];
            ++d[to[i][1]];
        }
        a[1] = n;
        toposort();
        for(int i = 1; i <= m; ++i)
            printf("%c","LR"[vis[i]]);
        return 0;
    }
    View Code

    E:Euclidean TSP

    题意:找到一个的c使得题目中的2个式子之和最小。

    题解:3分答案,这一定是一个凹函数。

    代码:

     1 #include<bits/stdc++.h>
     2 #define fio ios::sync_with_stdio(false);cin.tie(0)
     3 using namespace std;
     4 
     5 
     6 double n, p, s, v;
     7 double f(double c) {
     8     double t1 = (n * pow(log(n) / log(2), c * sqrt(2))) / (p * 1e9);
     9     double t2 = s * (1.0 + 1.0 / c) / v;
    10     return t1 + t2;
    11 }
    12 int main() {
    13     scanf("%lf%lf%lf%lf", &n, &p, &s, &v);
    14     double l = 0, r = 1e30;
    15     for (int i = 0; i < 1e4; i++) {
    16         double ll = (l + r) / 2;
    17         double rr = (ll + r) / 2;
    18         if (f(ll) > f(rr)) l = ll;
    19         else r = rr;
    20     }
    21     printf("%f %f
    ", f(l), l);
    22 }
    View Code

    F:Finding Lines

    题意:给你n个点,然后在让你添加上p个点,问你能不能满足至少一条直线上出现 (n+3)/4 个点。

    题解:随机生成p个点500次, 然后check。

    代码:

    #include<bits/stdc++.h>
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    using namespace std;
    
    const int N = 1e5 + 10;
    typedef long long ll;
    struct point {
        ll x, y;
        point (ll _x = 0, ll _y = 0) :x(_x), y(_y)  {}
        void read() {
            scanf("%I64d%I64d", &x, &y);
        }
        void out() {
            cout<<"x = "<<x<<" y = "<<y<<endl;
        }
        point operator - (const point &rhs) const {
            return point(x - rhs.x, y - rhs.y);
        }
    }p[N];
    
    ll cross(point a, point b) {
        return a.x * b.y - a.y * b.x;
    }
    
    int n, percent, need;
    int main() {
        srand(time(NULL));
        scanf("%d%d", &n, &percent);
        for (int i = 0; i < n; i++) p[i].read();
        if (n <= 2) {
            puts("possible");
            return 0;
        }
        int need = (n * percent) / 100;
        if ((n * percent) % 100 != 0) need++;
        int mx = 0;
        for (int _ = 0; _ < 500; _++) {
            random_shuffle(p, p + n);
            int cnt = 2;
            for (int i = 2; i < n; i++) if (cross(p[0] - p[1], p[i] - p[0]) == 0) cnt++;
            if (cnt >= need) {
                puts("possible");
                return 0;
            }
            mx = max(mx, cnt);
        }
        puts("impossible");
        return 0;
    }
    View Code


    G:Gathering

    题意:在平面上有n个点,然后现在让你找到一个点,使得所有点到这个点的曼哈顿距离只和最小,且不能有距离>d的点。

    题解:如果我们不考虑距离 > d的情况下, 那么最优解肯定就是所有点的x值的中位数, y值的中位数。

    现在我们多了一个限制性的条件, 那么我们先把这个可行域扣出来,可行域是一个斜着的正方形,那么最优解的那个点如果落在可行域之内,那么就是这个点, 但是如果落在外面的话,就会存在一种现象,如果当x更靠近最优解的点的时候, y可能会变得更远。

    对于上面的那个东西来说, 他会形成一个凹函数, 这个地方我们可以用三分去找到答案。

    我们每次三分x轴, 当x轴定下来之后,那么y就自然是选择可行范围内的位置中更靠近最优解的点,所以只需要一个三分就好了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    int x[N], y[N];
    LL A = INF, B = -INF, C = -INF, D = INF;
    LL midy;
    int n;
    LL cal(LL xx){
        LL uy = min(xx-C, A-xx);
        LL dy = max(B-xx, xx-D);
        if(uy < dy) return INF;
        LL ty;
        if(midy > uy) ty = uy;
        else if(midy < dy) ty = dy;
        else ty = midy;
        LL ret = 0;
        for(int i = 1; i <= n; ++i){
            ret += abs(x[i]-xx) + abs(y[i]-ty);
        }
        return ret;
    }
    int main(){
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
            scanf("%d%d", &x[i], &y[i]);
        LL d;
        scanf("%lld", &d);
        for(int i = 1; i <= n; ++i){
            A = min(A, x[i]+y[i]+d); B = max(B, x[i]+y[i]-d);
            C = max(C, x[i]-y[i]-d); D = min(D, x[i]-y[i]+d);
        }
        //cout << A << ' ' << B << ' '<< C << ' ' << D << endl;
        if(A < B || C > D) {
            puts("impossible");
            return 0;
        }
        sort(y+1, y+1+n);
        midy = y[(n+1)/2];
        LL lx = (C+B)/2, rx = (A+D)/2;
        //cout << lx << ' ' << rx << endl;
        while(lx + 2 < rx){
            LL lm = (lx+rx)/2 , rm = (lm+rx)/2;
            if(cal(lm) < cal(rm)) rx = rm;
            else lx = lm;
        }
        LL ans = INF;
        for(lx; lx <= rx; ++lx) ans = min(ans, cal(lx));
        printf("%lld
    ", ans);
        return 0;
    }
    View Code

    H:Hyacinth

    题意:给你一棵树,对于这棵树来说,每一个端点来说是有2个频率,任意2个相连的点,至少要有一个频率是相同的,一个频率如果有效,那么至少出现在一对相邻的点上,求一种构造方式使得有效频率最多。

    题解:先找到一个根,然后对于根来说随意分配2个值,然后对于一个新的点来说,先找到父亲的2个频率没出现2次的,找不到就随便一个,然后如果这个点有儿子,那么就来一个新的频率,如果没有儿子就把这个点的另一个频率赋值给这个点。

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    pll p[N];
    vector<int> vc[N];
    int tot;
    int vis[N];
    queue<int> q;
    void dfs(int o, int u){
        if(u == 1) {
            p[u].fi = 1;
            p[u].se = 2;
            vis[1] = vis[2] = 1;
            tot = 3;
            for(auto v : vc[u]){
                dfs(u, v);
            }
        }
        else {
            if(vc[u].size() == 1){
                p[u] = p[o];
                ++vis[p[u].fi];
                ++vis[p[u].se];
                return ;
            }
            if(vis[p[o].fi] >= 2)
                p[u].fi = p[o].se;
            else
                p[u].fi = p[o].fi;
            vis[p[u].fi]++;
            p[u].se = tot++;
            vis[p[u].se]++;
            for(auto v : vc[u]){
                if(v == o) continue;
                dfs(u, v);
            }
        }
    }
    int pp = 1;
    
    int main(){
        int n;
        scanf("%d", &n);
        for(int i = 1, u, v; i < n; ++i){
            scanf("%d%d", &u, &v);
            vc[u].pb(v); vc[v].pb(u);
        }
        dfs(0,1);
        for(int i = 1; i <= n; ++i){
            printf("%d %d
    ", p[i].fi, p[i].se);
        }
        return 0;
    }
    View Code

    I:Indoorienteering

    题意:有一副 n 个点的完全图,问你是否存在某个路使得,从某点出发,跑一圈会到这个点,其他点都恰好经过一次,且总路程为L。

    题解:对于这个东西,我们把这幅图割成2部分,1号点一定在左边,并且一定是这幅图的起点,我们枚举左边图的状态, 枚举左边图的另一个端点,然后爆搜右边图的状态,然后在爆搜左边图的确定端点之后的状态,然后二分check。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 20;
    LL d[N][N], l;
    int lf[N], lsz, rt[N], rsz;
    LL vc[100000], vsz;
    void cal(int b, int e){
        vsz = 0;
        do{
            LL cnt = 0;
            cnt += d[b][rt[1]] + d[e][rt[rsz]];
            for(int i = 2; i <= rsz; ++i)
                cnt += d[rt[i-1]][rt[i]];
            vc[++vsz] = cnt;
        }while(next_permutation(rt+1,rt+1+rsz));
        sort(vc+1, vc+1+vsz);
        vsz = unique(vc+1, vc+1+vsz) - vc - 1;
    }
    int c[N], csz;
    inline bool bck(LL v){
        if(v <= 0) return false;
        int p = lower_bound(vc+1, vc+1+vsz, v) - vc;
        if(vc[p] == v) return true;
        return false;
    }
    void check(int u, int v){
        csz = 0;
        for(int i = 1; i <= lsz; ++i){
            if(lf[i] == u || lf[i] == v) continue;
            c[++csz] = lf[i];
        }
        if(csz){
            do{
                LL tmp = l;
                tmp -= d[u][c[1]] + d[v][c[csz]];
                for(int i = 2; i <= csz; ++i){
                    tmp -= d[c[i-1]][c[i]];
                }
                if(bck(tmp)){
                    puts("possible");
                    exit(0);
                }
            }while(next_permutation(c+1, c+1+csz));
        }
        else{
            if(bck(l-d[u][v])){
                puts("possible");
                exit(0);
            }
        }
    }
    void solve(){
        int t = -1;
        for(int i = 2; i <= lsz; ++i){
            t = lf[i];
            cal(1,t);
            check(1,t);
        }
        if(t == -1) {
            cal(1,1);
            check(1,1);
        }
    }
    int main(){
        int n;
        scanf("%d%lld", &n, &l);
        for(int i = 0; i < n; ++i)
            for(int j = 0; j < n; ++j)
                scanf("%lld", &d[i][j]);
        int lnum = n/2 , rnum = n - lnum;
        int m = (1<<n);
        for(int i = 0; i < m; ++i){
            lsz = rsz = 0;
            for(int j = 0; j < n; ++j){
                if((i>>j)&1) lf[++lsz] = j;
                else rt[++rsz] = j;
            }
            if(lsz == lnum && lf[1] == 1)
                solve();
        }
        puts("impossible");
        return 0;
    }
    View Code

    J:Judging Troubles

    代码:

    #include<bits/stdc++.h>
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    using namespace std;
    
    map<string, int>mp1, mp2;
    int n, ans;
    int main() {
        fio;
        cin>>n;
        string tmp;
        for (int i = 0; i < n; i++) {
            cin>>tmp;
            mp1[tmp]++;
        }
        for (int i = 0; i < n; i++) {
            cin>>tmp;
            mp2[tmp]++;
        }
        for (auto it = mp1.begin(); it != mp1.end(); ++it) {
            ans += min(it->second, mp2[it->first]);
        }
        cout<<ans<<endl;
    }
    View Code

    K:Knapsack Collection

    题意:现在有一个长度为s的传送带,传送带上有n个物品,每个物品的位置在pi,现在每次拿一个物品要t秒,如果你站在传送带的位置上,那么你就会有东西传到你的面前,然后你就会用t的时间去拿这个东西。现在对于传送带的每个位置,你都会有一个拿完所有的物品的花费时间, 现在问你这个花费时间最小是多少, 最大是多少, 平均时间是多少。

    题解:我们枚举所有从所有有东西的位置开始,最小的时间一定会是从某个有东西的位置开始的,然后最大的时间一定是某个有东西的位置的后面,我们算出所有有东西的状态,然后上一个位置如果没有东西,就是这个位置的状态+1。 

    然后我们就模拟拿东西的过程,我们可以把自己不动传送带动的方式 -> 传送带不动 自己动来模拟。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL mod =  (int)1e9+7;
    const int N = 2100;
    int cnt[N];
    int a[N];
    LL tim[N];
    int n, s, t;
    LL cal(int x){
        LL ret = 0; int p = x;
        multiset<int> st;
        multiset<int>::iterator it;
        for(int i = 1; i <= n; ++i) st.insert(a[i]);
        while(!st.empty()){
            it = st.lower_bound(p);
            if(it == st.end()){
                ret += s - p;
                p = 0;
                it = st.lower_bound(p);
            }
            ret += (*it) - p + t;
            p = ((*it)+t) % s;
            st.erase(it);
        }
        return ret;
    }
    int main(){
        scanf("%d%d%d", &n, &s, &t);
        for(int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);
        sort(a+1, a+1+n);
        a[0] = -2;
        LL sum = 0;
        for(int i = 1; i <= n; ++i){
            if(a[i] == a[i-1]) tim[i] = tim[i-1];
            else {
                tim[i] = cal(a[i]);
                //sum += tim[i];
            }
        }
        LL mn = tim[1], mx = tim[1];
        for(int i = 2; i <= n; ++i){
            mn = min(mn, tim[i]);
            mx = max(mx, tim[i]);
        }
        for(int i = 1; i <= n; ++i){
            if(a[i] == a[i-1]) continue;
            int l = a[i-1] + 1, r = a[i];
            if(l == -1) l = a[n] + 1, r += s;
            //cout << l << ' ' << r << endl;
            int len = r - l + 1;
            mx = max(mx, tim[i]+len-1);
            sum += 1ll * (tim[i]+tim[i]+len-1) * len / 2;
        }
        cout << mn << endl;
        cout << mx << endl;
        LL gcd = __gcd(sum, 1ll*s);
        sum /= gcd;
        s /= gcd;
        cout << sum << '/' << s << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    C++ 字符数组函数与string函数
    std::vector介绍
    DirectX开发环境配置
    基于序列图像的三维体绘的视线投射算法
    关于灰度图和彩色图
    cin函数的一点理解
    两个getline 输入带空格的字符串
    彩色图转灰度图的原理和参考源码
    牛顿迭代法求一个数的平方根
    约瑟夫环问题
  • 原文地址:https://www.cnblogs.com/MingSD/p/9982603.html
Copyright © 2020-2023  润新知