8.14模拟赛

感觉今天题目都挺有意思的可能以后还会碰到类似的 (Fop_zz就是厉害)

T1题面

大意:给出n根木棍,每次可以把一根长为x的木棍分为 y 和 x - y,使得最终所有的长度出现的次数都为偶数次,例如 1 1 4 就是不合法的, 而 1 1 2 2 是合法的(操作次数小于等于n)

sol:因为木棍只可能变短,所以我维护了一个大根堆,每次查询最大值和次大值,使最大值变为和次大值一样,再把两者的差压入堆中,易证最多n次

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
int n, a[100005], cnt = 0, ans[100005][2];
int heap[100005], size = 0;
inline void Up(int x)
{
    while(x > 1)
    if (heap[x] > heap[x / 2])
    swap(heap[x], heap[x / 2]),
    x /= 2;
    else
    break;
}
inline void Down(int x)
{
    int y = x * 2;
    while (y <= size)
    {
        if (heap[y] < heap[y + 1] && y < size) y++;
        if (heap[x] < heap[y])
        swap(heap[x], heap[y]),
        x = y,
        y = x * 2;
        else
        break;
    }
}
inline void Insert(int x)
{
    heap[++size] = x;
    Up(size);
}
inline int GetTop()
{
    return heap[1];
}
inline void PopTop()
{
    swap(heap[1], heap[size]);
    size--;
    Down(1);
}
signed main()
{
    scanf("%lld", &n);
    int sum = 0;
    for(int i = 1; i <= n; i++)
    scanf("%lld", &a[i]), sum += a[i];
    if (sum & 1)
    {
        printf("-1\n");
        return 0;
    }
    for(int i = 1; i <= n; i++)
    Insert(a[i]);
    for(;size > 1;)
    {
        int x = GetTop();
        PopTop();
        int y = GetTop();
        PopTop();
        if (x != y)
        ans[++cnt][0] = x,
        ans[cnt][1] = x - y,
        Insert(x - y);
    }
    if (size == 1)
    {
        int x = GetTop();
        PopTop();
        ans[++cnt][0] = x / 2;
        ans[cnt][1] = x / 2;
    }
    printf("%lld\n", cnt);
    for(int i = 1; i <= cnt; i++)
    printf("%lld %lld\n", ans[i][0], ans[i][1]);
}
View Code

T2题面

类似于石子合并的经典题,只不过套了个高精,还要压位

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define Mod 1000000007
#define int long long
int power = 8, base = 100000000;
int n, b[305], g[305][305];
bool vis[305][305];
inline int sqr(int x){return x * x;}
struct Bignum
{
    int a[30];
    Bignum(){memset(a, 0, sizeof a);}
    Bignum(int num)
    {
        memset(a, 0, sizeof a);
        while(num)
        a[++a[0]] = num % base,
        num /= base;
    }
    inline void print()
    {
        printf("%lld", a[a[0]]);
        for(int i = a[0] - 1; i >= 1; i--)
        {
            int tmp = a[i];
            if (tmp < 10000000) putchar('0');
            if (tmp < 1000000) putchar('0');
            if (tmp < 100000) putchar('0');
            if (tmp < 10000) putchar('0');
            if (tmp < 1000) putchar('0');
            if (tmp < 100) putchar('0');
            if (tmp < 10) putchar('0');
            printf("%lld",tmp);
        }
        printf("\n");
    }
}f[305][305], zero, ans, one;
inline bool operator <(const Bignum &p, const Bignum &q)
{
    if (p.a[0] < q.a[0]) return true;
    if (p.a[0] > q.a[0]) return false;
    for(int i = p.a[0]; i >= 1; i--)
    if (p.a[i] != q.a[i]) return p.a[i] < q.a[i];
    return false;
}
inline Bignum max(Bignum p, Bignum &q)
{
    return (p < q) ? q : p;
}
inline Bignum operator +(const Bignum &p, const Bignum &q)
{
    Bignum pp;
    pp.a[0] = max(p.a[0], q.a[0]);
    for(int i = 1; i <= pp.a[0]; i++)
    {
        pp.a[i] += p.a[i] + q.a[i];
        pp.a[i + 1] += pp.a[i] / base;
        pp.a[i] %= base;
    }
    if (pp.a[pp.a[0] + 1]) pp.a[0]++;
    return pp;
}
inline Bignum dp(int l, int r)
{
    if (vis[l][r]) return f[l][r];
    if (l == r) return Bignum(0);
    vis[l][r] = 1;
    for(int i = l + 1; i <= r; i++)
    f[l][r] = max(f[l][r], dp(l, i - 1) + dp(i, r) + (Bignum)(sqr(g[l][i - 1] - g[i][r])));
    return f[l][r];
}
signed main()
{
    memset(vis, 0, sizeof vis);
    scanf("%lld", &n);
    for(int i = 1; i <= n; i++)
    scanf("%lld", &b[i]);
    for(int i = 1; i <= n; i++)
    {
        int now = 1LL;
        for(int j = i; j <= n; j++)
        now = now * b[j] % Mod,
        g[i][j] = now;
    }
    dp(1, n).print();
}
View Code

T3题面

线段树 不想说发

因为是and操作,一个数最多改log次, 暴力单点修改复杂度n*log(n)可过

#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
    char ch;
    int flag = 0, s = 0;
    while(!isdigit(ch)) flag |= (ch== '-'), ch = getchar();
    while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch - '0'), ch = getchar();
    return flag ? -s : s;
}
int n, m, a[100005];
struct xds
{
    int l, r, ma, sum;
}Tree[100005 << 3];
inline void pushup(int x)
{
    Tree[x].ma = max(Tree[x << 1].ma, Tree[x << 1 | 1].ma);
    Tree[x].sum = (Tree[x << 1].sum | Tree[x << 1 | 1].sum);
}
inline void build(int l, int r, int x)
{
    Tree[x].l = l;
    Tree[x].r = r;
    if (l == r)
    {
        Tree[x].ma = a[l];
        Tree[x].sum = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, x << 1);
    build(mid + 1, r, x << 1 | 1);
    pushup(x);
}
inline void change(int pos, int x, int val)
{
    if (Tree[x].l == Tree[x].r)
    {
        Tree[x].ma = val;
        Tree[x].sum = val;
        return;
    }
    int mid = (Tree[x].l + Tree[x].r) >> 1;
    if (pos <= mid) change(pos, x << 1, val);
    else change(pos, x << 1 | 1, val);
    pushup(x);
}
inline void updata(int l, int r, int x, int val)
{
    if ((Tree[x].sum & val) == Tree[x].sum) return;
    if (Tree[x].l == Tree[x].r)
    {
        Tree[x].ma &= val;
        Tree[x].sum &= val;
        return;
    }
    int mid = (Tree[x].l + Tree[x].r) >> 1;
    if (r <= mid) updata(l, r, x << 1, val);
    else if (l > mid) updata(l, r, x << 1 | 1, val);
    else updata(l, mid, x << 1, val), updata(mid + 1, r, x << 1 | 1, val);
    pushup(x);
}
inline int query(int l, int r, int x)
{
    if (l <= Tree[x].l && Tree[x].r <= r) return Tree[x].ma;
    int mid = (Tree[x].l + Tree[x].r) >> 1, res = 0;
    if (r <= mid) return query(l, r, x << 1);
    else if (l > mid) return query(l, r, x << 1| 1);
    else return max(query(l, mid, x<<1), query(mid + 1, r, x << 1 | 1));
}
signed main()
{
    n = read();
    m = read();
    for(int i = 1; i <= n; i++)
    a[i] = read();
    build(1, n, 1);
    char s[20];
    for(int i = 1, l, r, x; i <= m; i++)
    {
        scanf("%s", s + 1);
        l = read();
        r = read();
        if (s[1] == 'C')
        change(l, 1, r);
        if (s[1] == 'U')
        x = read(),
        updata(l, r, 1, x);
        if (s[1] == 'A')
        printf("%lld\n", query(l, r, 1));
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/gaojunonly1/p/9477861.html