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
原文地址:https://www.cnblogs.com/MingSD/p/9982603.html