Pbri

24-25 Winter Training

有些计算几何没写,有些字符串没写,有些题没补。

Long Round 1

原比赛链接:https://codeforces.com/gym/102770/

A

提前预处理日期的前缀和,模拟即可。

>#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#define MAXN 100010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
int ans;
bool leap_year(int x)
{
    if (x % 100 != 0)
        return (x % 4 == 0);
    return (x % 400 == 0);
}
int yDay(int x, int y, int z)
{
    if (y == 1 || y == 3 || y == 5 || y == 7 || y == 8 || y == 10 || y == 12)
        return 31;
    if (y == 2)
    {
        if (leap_year(x))
            return 29;
        return 28;
    }
    return 30;
}
int pd(int x, int y, int z)
{
    // printf("x=%d y=%d z=%d\n", x, y, z);
    if (x / 10 == 202)
        return 1;
    if (x % 1000 == 202)
        return 1;
    if (x % 100 == 20 && y / 10 == 2)
        return 1;
    if (x % 10 == 2 && y == 2)
        return 1;
    if (y == 20 && z / 10 == 2)
        return 1;
    if (y % 10 == 2 && z == 2)
        return 1;
    return 0;
}
int nextX(int x, int y, int z)
{
    if (y == 12 && z == 31)
        return x + 1;
    return x;
}
int nextY(int x, int y, int z)
{
    z++;
    int day = yDay(x, y, z);
    if (z > day)
    {
        y++;
        if (y == 13)
            y = 1;
    }
    return y;
}
int nextZ(int x, int y, int z)
{
    z++;
    int day = yDay(x, y, z);
    if (z <= day)
        return z;
    return 1;
}
int sum[10000][13][32];
void solve()
{
    ans = 0;
    int X1 = read(), Y1 = read(), Z1 = read();
    int X2 = read(), Y2 = read(), Z2 = read();
    printf("%d\n", sum[X2][Y2][Z2] - sum[X1][Y1][Z1] + pd(X1, Y1, Z1));
}
void work()
{
    int X1 = 2000, Y1 = 1, Z1 = 1;
    int X2 = 9999, Y2 = 12, Z2 = 31;
    while (X1 != X2 || Y1 != Y2 || Z1 != Z2)
    {
        int nx = nextX(X1, Y1, Z1);
        int ny = nextY(X1, Y1, Z1);
        int nz = nextZ(X1, Y1, Z1);
        sum[nx][ny][nz] = sum[X1][Y1][Z1] + pd(nx, ny, nz);
        X1 = nx, Y1 = ny, Z1 = nz;
        // printf("nx=%d ny=%d nz=%d\n", nx, ny, nz);
    }
}
int main()
{
    // freopen("data.in", "r", stdin);
    // freopen("A.out", "w", stdout);
    work();
    T = read();
    while (T--)
        solve();
    return 0;
}

B

前者线段树,后者用set即可。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#define MAXN 1000010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
int n, C, a[MAXN], ans1, ans2;
int mx[MAXN << 2];
#define lson (now << 1)
#define rson ((now << 1) + 1)
void push_up(int now)
{
    mx[now] = max(mx[lson], mx[rson]);
}
void ini(int now, int l, int r)
{
    if (l == r)
        mx[now] = C;
    else
    {
        int mid = (l + r) >> 1;
        ini(lson, l, mid);
        ini(rson, mid + 1, r);
        push_up(now);
    }
}
void update(int now, int l, int r, int w)
{
    if (l == r)
    {
        if (mx[now] == C)
            ans1++;
        mx[now] -= w;
    }
    else
    {
        int mid = (l + r) >> 1;
        if (mx[lson] >= w)
            update(lson, l, mid, w);
        else
            update(rson, mid + 1, r, w);
        push_up(now);
    }
}
map<int, int> mp;
void solve()
{
    ans1 = 0, ans2 = 0;
    mp.clear();
    n = read(), C = read();
    FUP(i, 1, n)
    a[i] = read();
    ini(1, 1, n);
    FUP(i, 1, n)
    {
        update(1, 1, n, a[i]);
    }

    mp[C - a[1]] = 1;
    ans2 = 1;
    FUP(i, 2, n)
    {
        map<int, int>::iterator it = mp.lower_bound(a[i]);
        if (it == mp.end())
        {
            mp[C - a[i]]++;
            ans2++;
        }
        else
        {
            mp[it->first]--;
            mp[it->first - a[i]]++;
            if (mp[it->first] == 0)
                mp.erase(it);
        }
    }
    printf("%d %d\n", ans1, ans2);
}
int main()
{
    T = read();
    while (T--)
        solve();
    return 0;
}

C

大卡常题,卡吐了。反正就是拿trie去模拟,或者用unordered_map大概也行?我猜的。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define MAXN 1010
#define MAXM 4000010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
int n, m, cnt;
ll sum[MAXM], ans;
char s[MAXN][MAXN];
int son[MAXM][26];
bool ok;
char tmps[MAXN];
void ins(string ss, int weight)
{
    int now = 0;
    int len = ss.length();
    FUP(i, 0, len - 1)
    {
        if (!son[now][ss[i] - 'a'])
        {
            son[now][ss[i] - 'a'] = ++cnt;
        }
        now = son[now][ss[i] - 'a'];
    }
    // printf("now=%d\n", now);
    sum[now] += weight;
}
void count(int len)
{
    // printf("tmps:%s\n", tmps + 1);
    int now = 0;
    if (!len)
        return;
    FUP(i, 1, len)
    {
        if (!son[now][tmps[i] - 'a'])
        {
            if (T == 2)
                puts("-1");
            ok = false;
            return;
        }
        now = son[now][tmps[i] - 'a'];
    }
    // printf("now=%d tot=%d sum=%lld\n", now, tot[now], sum[now]);
    ans += sum[now];
}
void work1(int num)
{
    int now = 1;
    while (now <= n)
    {
        // printf("now=%d ns=", now);
        int tmp = 0;
        FUP(i, now, n)
        {
            if (s[num][i] == '#')
                break;
            tmps[++tmp] = s[num][i];
        }
        tmps[tmp + 1] = 0;
        now += tmp + 1;
        // cout << ns << endl;
        count(tmp);
        if (!ok)
            return;
    }
}
void work2(int num)
{
    int now = 1;
    while (now <= n)
    {
        int tmp = 0;
        FUP(i, now, n)
        {
            if (s[i][num] == '#')
                break;
            tmps[++tmp] = s[i][num];
        }
        tmps[tmp + 1] = 0;
        now += tmp + 1;
        count(tmp);
        if (!ok)
            return;
    }
}
void solve()
{
    ok = true;
    FUP(i, 0, cnt)
    {
        sum[i] = 0;
        FUP(j, 0, 25)
        son[i][j] = 0;
    }
    cnt = 0;
    ans = 0;
    n = read(), m = read();
    FUP(i, 1, n)
    scanf("%s", s[i] + 1);
    FUP(i, 1, m)
    {
        string str;
        int w = 0;
        cin >> str >> w;
        ins(str, w);
    }
    // FUP(i, 1, cnt)
    // printf("i=%d tot=%d sum=%d\n", i, tot[i], sum[i]);
    //  line
    FUP(i, 1, n)
    {
        // printf("line %d\n", i);
        work1(i);
        if (!ok)
            return;
    }
    if (!ok)
        return;
    // printf("ans=%d\n", ans);
    //  column
    FUP(i, 1, n)
    {
        // printf("column %d\n", i);
        work2(i);
        if (!ok)
            return;
    }
    if (!ok)
        return;
    if (T == 2)
        printf("%lld\n", ans);
}
int main()
{
    // freopen("data.in", "r", stdin);
    T = read();
    FUP(tt, 1, T)
    {
        if (tt > 33700)
            printf("tt=%d\n", tt);
        solve();
    }

    return 0;
}

E

容易发现就是区间内前 \(k\) 大和一个平方和。于是使用可持久化平衡树即可。然而我忘记这个怎么写了,贺了以前自己的板子。但修改又怎么也修改不出来。很神奇啊!所以我选择了求前 \(len-k\) 小,然后用总和减去。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
#define MAXN 200010
#define INF 0x7fffffff
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0')
    {
        w = w * 10 - '0' + ch, ch = getchar();
    }
    return w * flg;
}
int max(int x, int y) { return x > y ? x : y; }
int min(int x, int y) { return x < y ? x : y; }
int abs(int x) { return x < 0 ? (-x) : x; }
int num;
struct mpto
{
    int data, id;
} a[MAXN];
struct mpbc
{
    int d, ys;
} c[MAXN];
bool cmp(mpto x, mpto y)
{
    return x.data < y.data;
}
int n, m, rt[MAXN];
struct zhuxishu
{
    int ls[MAXN * 20], rs[MAXN * 20], siz[MAXN * 20];
    ll sum[MAXN * 20];
    int tot;
    void build(int &p, int l, int r)
    {
        tot++;
        p = tot;
        if (l == r)
        {
            return;
        }
        int mid = (l + r) >> 1;
        build(ls[p], l, mid);
        build(rs[p], mid + 1, r);
    }
    void Insert(int &p, int pre, int l, int r, int x, int y)
    {
        tot++;
        p = tot;
        ls[p] = ls[pre];
        rs[p] = rs[pre];
        siz[p] = siz[pre] + 1;
        // printf("%d,%d,%d,%d\n",l,r,p,siz[p]);
        if (l == r)
        {
            sum[p] = sum[pre] + y;
            return;
        }
        int mid = (l + r) >> 1;
        if (mid >= x)
        {
            Insert(ls[p], ls[pre], l, mid, x, y);
        }
        else
        {
            Insert(rs[p], rs[pre], mid + 1, r, x, y);
        }
        sum[p] = sum[ls[p]] + sum[rs[p]];
    }
    int query(int p, int pre, int l, int r, int k)
    {
        if (l == r)
        {
            return c[l].ys * k;
        }
        int mid = (l + r) >> 1;
        // printf("%d,%d,%d,%d,%d\n",p,l,r,ls[p],siz[ls[p]]);
        if (siz[rs[p]] - siz[rs[pre]] >= k)
        {
            return query(rs[p], rs[pre], mid + 1, r, k);
        }
        return sum[rs[p]] - sum[rs[pre]] + query(ls[p], ls[pre], 1, mid, k - siz[rs[p]] + siz[rs[pre]]);
    }
} T;
int w[MAXN];
int main()
{
    n = read(), m = read();
    FUP(i, 1, n)
    {
        a[i].data = read();
        a[i].id = i;
        w[i] = a[i].data;
    }
    // 离散化
    sort(a + 1, a + n + 1, cmp);
    a[0].data = INF;
    FUP(i, 1, n)
    {
        if (a[i].data != a[i - 1].data)
        {
            num++;
        }
        c[a[i].id].d = num;
        c[num].ys = a[i].data;
    }
    // cout<<num<<endl;
    // 建主席树
    T.build(rt[0], 1, num);
    FUP(i, 1, n)
    {
        T.Insert(rt[i], rt[i - 1], 1, num, c[i].d, w[i]);
        printf("i=%d sum=%lld\n", i, T.sum[rt[i]]);
        // printf("%d,%d\n",rt[i],T.siz[rt[i]]);
    }
    // printf("%d",T.query(rt[1],rt[1],))
    // 查询
    FUP(i, 1, m)
    {
        int ql = read(), qr = read(), loc = read();
        // loc+=T.siz[rt[ql-1]];
        printf("%d\n", T.query(rt[qr], rt[ql - 1], 1, num, loc));
    }
    return 0;
}

F

诈骗题,如果两个 \(b\) 异号直接全 \(0\) 即可。否则你会发现我们很容易通过去修改某个向量的值去完成。要不然就是这个向量有 \(0\) 一类的,这时候再找个向量去配合一下就可以了。当且仅当这两个向量方向一致并且对应成比例的时候无解。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 100010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
int n;
double a[MAXN], b[MAXN];
double b1, b2;
void solve()
{
    n = read();
    FUP(i, 1, n)
    a[i] = read();
    b1 = read();
    FUP(i, 1, n)
    b[i] = read();
    b2 = read();
    if (b1 * b2 < 0)
    {
        FUP(i, 1, n)
        printf("0 ");
        puts("");
        return;
    }
    FUP(i, 1, n)
    {
        if (a[i] * b[i] < 0)
        {
            FUP(j, 1, i - 1)
            printf("0 ");
            printf("10000 ");
            FUP(j, i + 1, n)
            printf("0 ");
            puts("");
            return;
        }
        if (a[i] == 0 && b[i] == 0)
            continue;
        if (a[i] != 0 && b[i] != 0 && a[i] * b2 != b[i] * b1)
        {
            FUP(j, 1, i - 1)
            printf("0 ");
            printf("%lf ", (-b1 / a[i] - b2 / b[i]) / 2);
            FUP(j, i + 1, n)
            printf("0 ");
            puts("");
            return;
        }
        // 1
        if (a[i] == 0 && b1 > 0)
        {
            FUP(j, 1, i - 1)
            printf("0 ");
            if (b[i] > 0)
                printf("-10000 ");
            else
                printf("10000 ");
            FUP(j, i + 1, n)
            printf("0 ");
            puts("");
            return;
        }
        // 2
        if (b[i] == 0 && b2 > 0)
        {
            FUP(j, 1, i - 1)
            printf("0 ");
            if (a[i] > 0)
                printf("-10000 ");
            else
                printf("10000 ");
            FUP(j, i + 1, n)
            printf("0 ");
            puts("");
            return;
        }
        // 3
        if (a[i] == 0 && b1 < 0)
        {
            FUP(j, 1, i - 1)
            printf("0 ");
            if (b[i] > 0)
                printf("10000 ");
            else
                printf("-10000 ");
            FUP(j, i + 1, n)
            printf("0 ");
            puts("");
            return;
        }
        // 4
        if (b[i] == 0 && b2 < 0)
        {
            FUP(j, 1, i - 1)
            printf("0 ");
            if (a[i] > 0)
                printf("10000 ");
            else
                printf("-10000 ");
            FUP(j, i + 1, n)
            printf("0 ");
            puts("");
            return;
        }
    }
    puts("No");
}
int main()
{
    T = read();
    while (T--)
        solve();
    return 0;
}

G

dp题。考虑每次选择的向上吹的速度必须逐次增大,要不然你走了条劣于直线的路,中间经过的点还更菜,这不就亏麻了。而且因为你下一个点比现在更好,所以只要自己的高度正好飞到下个点,即到了之后速度为零就可以。所以按照向上速度建 \(DAG\) 然后跑dp就好了。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define MAXN 4010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
db sx, sy, tx, ty;
db vf, vp, vh;
int n;
int deg[MAXN];
bool ari[MAXN];
db nx[MAXN], ny[MAXN], vu[MAXN];
vector<pair<int, db>> to[MAXN];
db dis(db a, db b, db c, db d)
{
    return sqrt((c - a) * (c - a) + (d - b) * (d - b));
}
db re[MAXN];
void dfs(int u)
{
    for (auto p : to[u])
    {
        int v = p.first;
        re[v] = min(re[v], re[u] + p.second);
        deg[v]--;
        if (!deg[v])
            dfs(v);
    }
}
void cledfs(int u)
{
    ari[u] = false;
    for (auto p : to[u])
    {
        int v = p.first;
        deg[v]--;
        if (!deg[v])
            cledfs(v);
    }
}
void solve()
{

    sx = read(), sy = read(), tx = read(), ty = read();
    vf = read(), vp = read(), vh = read();
    n = read();
    FUP(i, 1, n + 2)
    {
        to[i].clear();
        deg[i] = 0;
        re[i] = LLINF;
        ari[i] = true;
    }
    re[1] = 0;
    FUP(i, 1, n + 1)
    {
        nx[i] = read(), ny[i] = read(), vu[i] = read();
    }
    nx[n + 2] = tx, ny[n + 2] = ty, vu[n + 2] = INF;
    FUP(i, 1, n + 2)
    {
        if (vu[i] <= vp)
            continue;
        FUP(j, 1, n + 2)
        {
            if (i == j || vu[j] <= vp || vu[j] <= vu[i])
                continue;
            deg[j]++;
            db t = dis(nx[i], ny[i], nx[j], ny[j]) / vh;
            // printf("i=%d j=%d w=%.5lf\n", i, j, t + t * vp / (vu[i] - vp));
            to[i].push_back(make_pair(j, t + t * vp / (vu[i] - vp)));
        }
    }
    FUP(i, 2, n + 2)
    {
        if (deg[i] == 0)
            cledfs(i);
    }
    FUP(i, 1, n + 2)
    // printf("i=%d ari=%d\n", i, ari[i]);
    dfs(1);
    printf("%.10lf\n", re[n + 2]);
}
int main()
{
    T = read();
    while (T--)
        solve();
    return 0;
}

H

直接将每个点和每条线段去投影一下,然后把投影出的线段端点按坐标排序,维护每个阶段内有多少个点照不到自己就行了。注意考虑某个端点在自己这个点上方的情况,直接搞到2e9就行了。然后如果完全在自己上面,就不用考虑。如果覆盖住了这个点,就全图覆盖一下。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 510
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
int n, m;
db ans;
int cnt[MAXN];
int num;
struct Point
{
    db x, y;
} p[MAXN];
struct Segment
{
    Point u, v;
} s[MAXN];
int tot;
struct Shadow
{
    db x;
    int id, typ;
} sha[MAXN * MAXN * 2];
bool cmp(Shadow x, Shadow y)
{
    return x.x < y.x;
}
void make_shadow(Point pf, Segment sf, int id)
{
    Shadow s1, s2;
    if ((pf.x - sf.u.x) * (sf.v.y - sf.u.y) == (pf.y - sf.u.y) * (sf.v.x - sf.u.x) && (pf.x - sf.u.x) * (pf.x - sf.v.x) <= 0)
    {
        s1.x = -2e9, s2.x = 2e9;
        s1.id = id, s2.id = id;
        s1.typ = 1, s2.typ = -1;
    }
    else
    {
        if (sf.u.y > sf.v.y)
            swap(sf.u, sf.v);
        if (sf.u.y > pf.y)
            return;
        s1.x = pf.x - pf.y * (pf.x - sf.u.x) / (pf.y - sf.u.y);
        s1.id = id;
        if (sf.v.y > pf.y)
        {
            db nx = sf.u.x + (pf.y - sf.u.y) * (sf.v.x - sf.u.x) / (sf.v.y - sf.u.y);
            if (nx > pf.x)
                s2.x = 2e9;
            else
                s2.x = -2e9;
        }
        else
        {
            s2.x = pf.x - pf.y * (pf.x - sf.v.x) / (pf.y - sf.v.y);
        }
        s2.id = id;
        if (s1.x > s2.x)
            swap(s1, s2);
        s1.typ = 1, s2.typ = -1;
        // printf("pf.x=%lf pf.y=%lf sf.u.x=%lf sf.u.y=%lf s1.x=%lf s2.x=%lf\n", pf.x, pf.y, sf.u.x, sf.u.y, s1.x, s2.x);
    }
    sha[++tot] = s1;
    sha[++tot] = s2;
}
void solve()
{
    ans = 0;
    tot = 0;
    num = 0;
    FUP(i, 1, n)
    cnt[i] = 0;

    n = read(), m = read();
    FUP(i, 1, n)
    {
        p[i].x = read();
        p[i].y = read();
    }
    FUP(i, 1, m)
    {
        s[i].u.x = read(), s[i].u.y = read();
        s[i].v.x = read(), s[i].v.y = read();
    }
    FUP(i, 1, n)
    {
        FUP(j, 1, m)
        {
            make_shadow(p[i], s[j], i);
        }
    }
    sort(sha + 1, sha + tot + 1, cmp);

    db lst = 0;
    bool exi = 0;
    FUP(i, 1, tot)
    {

        if (sha[i].typ == 1)
        {
            cnt[sha[i].id]++;
            if (cnt[sha[i].id] == 1)
            {
                num++;
                if (num == n)
                {
                    exi = 1;
                    lst = sha[i].x;
                }
            }
        }
        else
        {
            cnt[sha[i].id]--;
            if (cnt[sha[i].id] == 0)
            {
                num--;
                if (num == n - 1)
                {
                    if (exi)
                    {
                        exi = 0;
                        ans += sha[i].x - lst;
                        lst = 0;
                    }
                }
            }
        }
        // printf("i=%d x=%lf id=%d typ=%d num=%d lst=%lf ans=%lf\n", i, sha[i].x, sha[i].id, sha[i].typ, num, lst, ans);
    }
    if (ans > 1e9)
        puts("-1");
    else
        printf("%.10lf\n", ans);
}
int main()
{
    T = read();
    while (T--)
        solve();
    return 0;
}

I

最后必定形成好几个环。只需考虑最大环即可。用 unordered_map 即可避免离散化。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <unordered_map>
#include <vector>
#define MAXN 100010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
int n, ans;
pair<int, int> pr[MAXN];
unordered_map<int, int> fa, cnt;
int find(int u)
{
    if (fa[u] == 0)
        return u;
    return fa[u] = find(fa[u]);
}
void solve()
{
    ans = 0;
    fa.clear(), cnt.clear();
    n = read();
    FUP(i, 1, n)
    {
        int u = read(), v = read();
        pr[i].first = u;
        pr[i].second = v;
        int ufa = find(u);
        int vfa = find(v);
        // printf("u=%d v=%d ufa=%d vfa=%d\n", u, v, ufa, vfa);
        if (ufa == vfa)
            continue;
        fa[ufa] = vfa;
    }
    FUP(i, 1, n)
    {
        int ufa = find(pr[i].first);
        int vfa = find(pr[i].second);
        cnt[ufa]++;
        cnt[vfa]++;
        ans = max(ans, max(cnt[ufa], cnt[vfa]));
    }
    printf("%d\n", ans / 2);
}
int main()
{
    // freopen("data.in", "r", stdin);
    T = read();
    while (T--)
        solve();
    return 0;
}

K

模拟判断即可。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 100010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
int n;
int a[MAXN], b[MAXN];
void solve()
{
    n = read();
    FUP(i, 1, n)
    a[i] = read();
    FUP(i, 1, n)
    b[i] = read();
    FUP(i, 1, n)
    {
        if (b[i] > a[i] * 3)
        {
            printf("%d\n", i);
            return;
        }
    }
    puts("-1");
}
int main()
{
    T = read();
    while (T--)
        solve();
    return 0;
}

Short Round 1

A

link:https://codeforces.com/problemset/problem/2000/B

模拟判断即可

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 200010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
int n, a[MAXN];
bool vis[MAXN];
void solve()
{
    n = read();
    FUP(i, 0, n + 1)
    vis[i] = false;
    FUP(i, 1, n)
    a[i] = read();
    vis[a[1]] = true;
    FUP(i, 2, n)
    {
        if (!vis[a[i] - 1] && !vis[a[i] + 1])
        {
            puts("NO");
            return;
        }
        vis[a[i]] = true;
    }
    puts("YES");
}
int main()
{
    T = read();
    while (T--)
        solve();
    return 0;
}

B

link:https://codeforces.com/problemset/problem/2028/B

忘了啥题了,光记得考虑一下 \(b=0\) 的情况了。别的情况显然都可以。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 100010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
ll read()
{
    ll w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
ll n, b, c;
void solve()
{
    n = read(), b = read(), c = read();
    if (b == 0)
    {
        if (c < n - 2)
            puts("-1");
        else
        {
            if (c >= n)
                printf("%lld\n", n);
            else
                printf("%lld\n", n - 1);
        }
    }
    else
    {
        if (c >= n)
            printf("%lld\n", n);
        else
        {
            ll cnt = (n - c - 1) / b + 1;
            printf("%lld\n", n - cnt);
        }
    }
}
int main()
{
    T = read();
    while (T--)
        solve();
    return 0;
}

C

link:https://codeforces.com/problemset/problem/1983/D

操作不改变逆序对奇偶性。奇偶性相同时,直接大力冒泡排序就可以证明一定可以。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MAXN 100010
#define MAXV 200010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int T;
int n, a[MAXN], b[MAXN], c[MAXN], d[MAXN];
int sum1[MAXV], sum2[MAXV];
int lbt(int x)
{
    return x & (-x);
}
void add1(int x, int d)
{
    for (int i = x; i <= 2e5; i += lbt(i))
    {
        sum1[i] += d;
    }
}
void add2(int x, int d)
{
    for (int i = x; i <= 2e5; i += lbt(i))
    {
        sum2[i] += d;
    }
}
int query1(int x)
{
    int re = 0;
    for (int i = x; i > 0; i -= lbt(i))
    {
        re += sum1[i];
    }
    return re;
}
int query2(int x)
{
    int re = 0;
    for (int i = x; i > 0; i -= lbt(i))
    {
        re += sum2[i];
    }
    return re;
}
void solve()
{

    n = read();
    FUP(i, 1, n)
    a[i] = c[i] = read();
    FUP(i, 1, n)
    b[i] = d[i] = read();
    sort(c + 1, c + n + 1);
    sort(d + 1, d + n + 1);
    FUP(i, 1, n)
    {
        if (c[i] != d[i])
        {
            puts("NO");
            return;
        }
    }
    int cnt1 = 0, cnt2 = 0;
    FUP(i, 1, n)
    {
        cnt1 = (cnt1 + i - 1 - query1(a[i])) % 2;
        cnt2 = (cnt2 + i - 1 - query2(b[i])) % 2;
        // printf("i=%d query1=%d query2=%d\n", i, i - 1 - query1(a[i]), i - 1 - query2(b[i]));
        add1(a[i], 1);
        add2(b[i], 1);
    }
    if (cnt1 == cnt2)
        puts("YES");
    else
        puts("NO");
    FUP(i, 1, n)
    {
        add1(a[i], -1);
        add2(b[i], -1);
    }
}
int main()
{
    T = read();
    while (T--)
        solve();
    return 0;
}

D

link:https://codeforces.com/problemset/problem/1635/E

只要有关系就一定方向相反。于是可以二分图染色确定方案。然后按照关系的种类确定谁在前谁在后。然后根据先后顺序建图,如果建出来个 \(DAG\) ,那么一定有解,否则无解。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define MAXN 200010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
int n, m;
int uu[MAXN], vv[MAXN], typ[MAXN];
vector<int> to[MAXN];
int col[MAXN];
bool no;
void color(int u, int c)
{
    col[u] = c;
    for (auto v : to[u])
    {
        if (col[v] == 0)
            color(v, -c);
        else
        {
            if (col[v] * col[u] == 1)
            {
                no = true;
                return;
            }
        }
    }
}
vector<int> adj[MAXN];
int deg[MAXN];
int dfn[MAXN];
int cnt;
void dfs(int u)
{
    dfn[u] = ++cnt;
    for (auto v : adj[u])
    {
        deg[v]--;
        if (deg[v] == 0)
            dfs(v);
    }
}
int main()
{
    n = read(), m = read();
    FUP(i, 1, m)
    {
        typ[i] = read(), uu[i] = read(), vv[i] = read();
        to[uu[i]].push_back(vv[i]);
        to[vv[i]].push_back(uu[i]);
    }
    FUP(i, 1, n)
    {
        if (col[i] != 0)
            continue;
        color(i, 1);
        if (no)
        {
            puts("NO");
            return 0;
        }
    }
    FUP(i, 1, m)
    {
        if (col[uu[i]] == 1 && col[vv[i]] == -1)
        {
            if (typ[i] == 1)
            {
                adj[vv[i]].push_back(uu[i]);
                deg[uu[i]]++;
            }
            else
            {
                adj[uu[i]].push_back(vv[i]);
                deg[vv[i]]++;
            }
        }
        else
        {
            if (typ[i] == 1)
            {
                adj[uu[i]].push_back(vv[i]);
                deg[vv[i]]++;
            }
            else
            {
                adj[vv[i]].push_back(uu[i]);
                deg[uu[i]]++;
            }
        }
    }
    FUP(i, 1, n)
    {
        if (dfn[i])
            continue;
        if (deg[i])
            continue;
        dfs(i);
    }
    if (cnt < n)
    {
        puts("NO");
        return 0;
    }
    puts("YES");
    FUP(i, 1, n)
    {
        if (col[i] == 1)
            printf("R %d\n", dfn[i]);
        else
            printf("L %d\n", dfn[i]);
    }
    return 0;
}

E

links:https://codeforces.com/problemset/problem/1981/D

很有意思的题。首先发现我们应该选择质数,因为质数可以保证乘积分解的唯一性,不会出现类似于 \(6\times 2=3\times 4\) 一类的神经病情况。选了质数之后,就建图,找欧拉路径。注意这里可以有自环,但自环这个度数不属于欧拉路径存在的度数要求里的那个度数。然后注意需要奇数个质数的时候,每个点度数都是偶数,完全ok。偶数边就不大行了,所以需要去掉 \(2-3、4-5\cdot\cdot\cdot\) ,当然 \(1-n\) 需要留着,因为我们想要的是欧拉路径而非欧拉回路。然后跑那个 \(h\) 开头的字母的算法就好了。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define MAXN 300010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define db double
#define FUP(i, x, y) for (int i = (x); i <= (y); i++)
#define FDW(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
int read()
{
    int w = 0, flg = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            flg = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        w = w * 10 + ch - '0', ch = getchar();
    return w * flg;
}
const int VN = 300000;
int pn, pri[MAXN];
bool vis[MAXN];
void init()
{
    FUP(i, 2, VN)
    {
        if (!vis[i])
        {
            pri[++pn] = i;
        }
        FUP(j, 1, pn)
        {
            if (i * pri[j] > VN)
                break;
            vis[i * pri[j]] = true;
            if (i % pri[j] == 0)
                break;
        }
    }
}
int T;
bool ck(int mid, int n)
{
    if (mid & 1)
    {
        if (1ll * mid * (mid + 1) / 2 >= n - 1)
            return true;
        return false;
    }
    else
    {
        if (1ll * mid * (mid + 1) / 2 - mid / 2 + 1 >= n - 1)
            return true;
        return false;
    }
}
int head[MAXN], ednum;
int edid;
bool edvis[2100010];
struct edge
{
    int nxt, to, id;
} ed[2100010];
void add_Edge(int u, int v, int mat)
{
    // printf("u=%d v=%d mat=%d\n", u, v, mat);
    ednum++;
    ed[ednum].nxt = head[u];
    ed[ednum].to = v;
    ed[ednum].id = edid;
    if (mat)
    {
        edid++;
        ed[ednum].id++;
    }
    head[u] = ednum;
}
vector<int> ans;
int n;
void dfs(int u)
{
    // printf("u=%d\n", u);
    for (int &i = head[u]; i; i = ed[i].nxt)
    {
        int v = ed[i].to;
        int id = ed[i].id;
        if (edvis[id])
            continue;
        // printf("u=%d v=%d id=%d\n", u, v, id);
        edvis[id] = true;
        dfs(v);
        if ((int)ans.size() == n)
            return;
    }
    if ((int)ans.size() == n)
        return;
    ans.push_back(u);
}
void solve(int num)
{
    n = read();
    if (n == 2)
    {
        puts("1 1");
        return;
    }
    if (n == 3)
    {
        puts("1 1 2");
        return;
    }
    if (n == 4)
    {
        puts("1 1 2 2");
        return;
    }

    int l = 1, r = n;
    int re = -1;
    while (l <= r)
    {
        int mid = (l + r) >> 1;
        if (ck(mid, n))
            re = mid, r = mid - 1;
        else
            l = mid + 1;
    }

    // printf("re=%d\n", re);

    if (re & 1)
    {
        FUP(i, 1, re)
        add_Edge(i, i, 1);
        FUP(i, 1, re)
        {
            FUP(j, i + 1, re)
            {
                add_Edge(i, j, 1);
                add_Edge(j, i, 0);
            }
        }
    }
    else
    {
        FUP(i, 1, re)
        add_Edge(i, i, 1);
        FUP(i, 1, re)
        {
            if (i % 2 == 1)
            {
                add_Edge(i, i + 1, 1);
                add_Edge(i + 1, i, 0);
            }
            FUP(j, i + 2, re)
            {
                add_Edge(i, j, 1);
                add_Edge(j, i, 0);
            }
        }
    }
    dfs(1);

    FUP(i, 1, re)
    {
        head[i] = 0;
    }
    FUP(i, 1, ednum)
    {
        ed[i].nxt = ed[i].to = ed[i].id = 0;
    }
    for (auto x : ans)
        printf("%d ", pri[x]);
    puts("");

    FUP(i, 1, edid)
    edvis[i] = 0;
    ednum = edid = 0;
    ans.clear();
}
int main()
{
    init();
    T = read();
    FUP(i, 1, T)
    solve(i);
    return 0;
}
posted @ 2025-02-20 21:54  Pbri  阅读(16)  评论(0)    收藏  举报