zoukankan      html  css  js  c++  java
  • [AtCoder]AtCoder Regular Contest 082

    C - Together

    题意

    给定$N$个数,求它们或加一或减一或不变的众数。

    题解

    没什么好说的。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5+9;
    int cnt[N];
    inline int read() {
        int s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    int main() {
        int n = read();
        for (int i = 1; i <= n; i++) {
            int ai = read();
            cnt[ ai ]++, cnt[ ai+1 ]++, cnt[ ai-1 ]++;
        }
        int res = 0;
        for (int i = 0; i <= 1e5; i++) res = max(res, cnt[i]);
        return 0 * printf("%d
    ", res);
    }
    
    

    D - Derangement

    题意

    给定$N$个数的一个排列,每次只能交换相邻两数,求最少的交换次数使得$p_i eq i$。

    题解

    模拟一下,如果碰到$p_i=i$就把它和后面一个数交换。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e5+9;
    int p[N];
    inline int read() {
        int s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    int main() {
        int n = read();
        for (int i = 1; i <= n; i++) p[i] = read();
        int res = 0;
        for (int i = 1; i < n; i++) if (p[i] == i) res++, swap(p[i], p[i + 1]);
        if (p[n] == n) res++;
        return 0 * printf("%d
    ", res);
    }
    

    E - ConvexScore

    题意

    给定$N$个点$(x_i,y_i)$,定义这$N$个点的子集$S$为“凸多边形集”当且仅当$S$中所有点恰好构成一个凸多边形。对一个“凸多边形集”$S$,定义它的$score$为$2^{n-|S|}$,其中$n$为$S$构成的凸多边形包含(包括边上)的$N$个点中的点数。求所有“凸多边形集”的$score$之和对$998244353$取模的结果。

    题解

    题目要我们求的$2^{n-|S|}$对应的是一种集合取点的方案。
    我们考虑这$N$个点的任意子集$X$要被计算$score$,当且仅当它的凸包面积为正。
    再进一步,计算时任意凸包面积为正的子集对$score$的贡献为$1$,因为你把凸包上的点作为“凸多边形集”,其余的点作为一种取点的方案,恰好对应了“凸多边形集”的所有取点方案。
    然后我们就只要从$2^N$中把能组成直线的点集去掉。(注意不要重复算单点和空集的情况)
    去除共线的点集时,我们考虑枚举$N^2$个点对组成的线段,先把斜率化成最简分数$hash$一下排个序,然后对每个线段并查集维护即可。时间复杂度:$Theta (N^2logN)$。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int Q = 998244353;
    const int N = 209;
    ll x[N], y[N], p[N], f[N], size[N];
    inline int read() {
        int s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    inline int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    inline int findSet(int x) {
        return f[x] == x ? x : f[x] = findSet(f[x]);
    }
    inline void unionSet(int x, int y) {
        int fx = findSet(x), fy = findSet(y);
        if (fx != fy) {
            f[fy] = fx;
            size[fx] += size[fy];
        }
    }
    struct Seg {
        int p, q; ll hash;
        bool operator < (const Seg &rhs) const {
            return hash < rhs.hash;
        }
    };
    vector<Seg> seg;
    int main() {
        p[0] = 1;
        for (int i = 1; i < N; i++) {
            p[i] = p[i - 1] << 1, p[i] %= Q;
        }
        int n = read();
        for (int i = 1; i <= n; i++) {
            x[i] = read(), y[i] = read();
        }
        ll res = (p[n] - n - 1) % Q;
        for (int i = 1; i < n; i++) {
            for (int j = i + 1; j <= n; j++) {
                int dx = x[i] - x[j], dy = y[i] - y[j], g = gcd(dx, dy);
                dx /= g, dy /= g;
                if (dx == 0) dy = 1;
                if (dy == 0) dx = 1;
                if (dx < 0) dx *= -1, dy *= -1;
                Seg s; s.p = i, s.q = j, s.hash = dx * 100000 + dy;
                seg.push_back(s);
            }
        }
        sort(seg.begin(), seg.end());
        for (int i = 0, j = 0; i < seg.size(); i = j) {
            for (int k = 1; k <= n; k++) {
                f[k] = k, size[k] = 1;
            }
            for (; j < seg.size() && seg[i].hash == seg[j].hash; j++) {
                unionSet(seg[j].p, seg[j].q);
            }
            for (int k = 1; k <= n; k++) {
                if (f[k] == k && size[k] >= 2) {
                    res -= (p[ size[k] ] - size[k] - 1), res += Q, res %= Q;
                }
            }
        }
        printf("%lld
    ", res);
        return 0;
    }
    

    F - Sandglass

    题意

    给定一个总容量为$X$的沙漏,初始状态$A$部分有$a$克沙子,$B$部分有$X-a$克沙子,每秒钟掉下来$1$克沙子。有$K$个$r_i$时刻会将沙漏倒置。现在有$Q$个询问$(t_i,a_i)$,初始$A$部分在上面且有沙子$a_i$克。求在$t_i$时刻$A$部分的沙子多少克。

    题解

    假设$A$部分沙子初始有$x$克,在$t$时刻时的沙子有$f_t(x)$克。
    当某时刻$A$部分有$y$克沙子时,下一秒钟:
    若$A$部分在上面,则$f_t(x)=g_1(y)=max(y-1,0)$;
    若$A$部分在下面,则$f_t(x)=g_2(y)=max(y+1,X)$.
    因为$f_t$是在函数$g_1,g_2$下封闭的,所以它一定是个如下的线性分段函数:
    $egin{equation}
    f_t(x)=
    egin{cases}
    a+c,&0leq xleq a ewline
    x+c,&aleq xleq b ewline
    b+c,&bleq xleq X
    end{cases}
    end{equation}$
    对于每个$t$维护上式中的$a,b,c$,然后回答询问即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int K = 1e5+9;
    ll r[K];
    inline ll read() {
        ll s = 1, a = 0; char ch = getchar();
        while (ch < '0' || ch > '9') {if (ch == '-') s = -1; ch = getchar();}
        while (ch >= '0' && ch <= '9') {a = a * 10 + ch - '0'; ch = getchar();}
        return s * a;
    }
    inline void turn(ll &v, ll x) {
        if (v < 0) v = 0;
        if (v > x) v = x;
    }
    int main() {
        ll x = read(), k = read();
        for (int i = 1; i <= k; i++) r[i] = read();
        ll q = read();
        ll low = 0, mid = 0, upp = x;
        int i = 1, sign = -1;
        while (q--) {
            ll t = read(), a = read();
            while (i <= k && r[i] <= t) {
                ll dta = (r[i] - r[i - 1]) * sign;
                low += dta, upp += dta, mid += dta;
                turn(low, x), turn(mid, x);
                i++, sign *= -1;
            }
            ll res = a + mid;
            ll dta = (t - r[i - 1]) * sign;
            if (res < low) res = low;
            if (res > upp) res = upp;
            res += dta, turn(res, x);
            printf("%lld
    ", res);
        }
        return 0;
    }
    
  • 相关阅读:
    可变形参 Day07
    流程控制 Day06
    基本数据类型的值传递 和引用数据类型的引用传递 Day06
    一维数组的求平均成绩 Day06
    一维数组的初始化及遍历 Day06
    字符串分割+二维数组 Day15练习
    Java对数组和列表的排序1.8新特性
    Java Stream
    JPA学习(六、JPA_JPQL)
    JPA学习(五、JPA_二级缓存)
  • 原文地址:https://www.cnblogs.com/jstztzy/p/7470618.html
Copyright © 2011-2022 走看看