1. 程式人生 > 其它 >NOIP提高組模擬賽24[matrix block graph]

NOIP提高組模擬賽24[matrix block graph]

T1. 大力狀壓。沒了

#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <sstream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <map>
#include <deque>
#include <bitset>
#include <list>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

int read()
{
    int x = 0;
    char c;
    bool f = 0;
    while (!isdigit(c = getchar()))
    {
        if (c == '-')
        {
            f = 1;
        }
    }
    do
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
    } while (isdigit(c = getchar()));
    if (f)
    {
        return -x;
    }
    return x;
}

const int maxn = 12, maxk = 1030;

int n, m, MAX;

char str[maxn];
int p[maxn][maxn];
int a[maxn];
int f[maxn][maxk][maxk], g[maxn][maxk], las[maxn][maxk];

int main()
{
    #ifndef DEBUG
    freopen("matrix.in", "r", stdin);
    freopen("matrix.out", "w", stdout);
    #endif
    n = read(), m = read();
    for (int i = 1; i <= n; ++i)
    {
        scanf("%s", str);
        for (int j = 0; j < m; ++j)
        {
            a[i] |= ((str[j] - '0') << j);
        }
    }
    int MAX = 1 << m;
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
            p[i][j] = read();
        }
        for (int j = 0; j < MAX; ++j)
        {
            int tmp = 0;
            for (int k = 0; k < m; ++k)
            {
                if (j & (1 << k))
                {
                    tmp += p[i][k];
                }
            }
            g[i][j] = tmp;
        }
    }
    memset(f, 0x3f, sizeof f);
    for (int i = 0; i < MAX; ++i)
    {
        for (int j = 0; j < MAX; ++j)
        {
            f[0][i][j] = 0;
        }
    }
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < MAX; ++j)
        {
            for (int u = 0; u < MAX; ++u)
            {
                if ((j | u) != MAX - 1)
                {
                    continue;
                }
                for (int k = 0; k < MAX; ++k)
                {
                    if (f[i][j][k] == 0x3f3f3f3f)
                    {
                        continue;
                    }
                    int tmp = u | ((u << 1) & (MAX - 1)) | (u >> 1) | k | a[i + 1];
                    if (i == 0)
                    {
                        tmp = u | ((u << 1) & (MAX - 1)) | (u >> 1) | a[i + 1];
                    }
                    f[i + 1][tmp][u] = min(f[i + 1][tmp][u], f[i][j][k] + g[i + 1][u]);
                }
            }
        }
    }
	int ans = 0x7fffffff;
    for (int i = 0; i < MAX; ++i)
    {
        ans = min(ans, f[n][MAX - 1][i]);
    }
    printf("%d\n", ans);
}

T2. 第一問簡單題排個序就完了,第二問線段樹維護 (這兩問一點關係沒有……)

#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <deque>
#include <bitset>
#include <list>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

int read()
{
    int x = 0;
    char c;
    bool f = 0;
    while (!isdigit(c = getchar()))
    {
        if (c == '-')
        {
            f = 1;
        }
    }
    do
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
    } while (isdigit(c = getchar()));
    if (f)
    {
        return -x;
    }
    return x;
}

const int maxn = 5e5 + 10, mod = 1e9 + 7;

int n;

struct data
{
    int key, val;
} a[maxn];

bool cmp(const data &a, const data &b)
{
    if (a.val == b.val)
    {
        return a.key < b.key;
    }
    return a.val > b.val;
}

bool cmp2(const data &a, const data &b)
{
    if (a.val == b.val)
    {
        return a.key < b.key;
    }
    return a.val < b.val;
}

struct SegmentTree
{
    #define ls (p << 1)
    #define rs ((p << 1) | 1)
    struct data
    {
        int val, key, now, from;
        int lazy, mn;
    } tr[maxn << 2];
    int mim(int x, int y)
    {
        if (x == -1)
        {
            return y;
        }
        if (y == -1)
        {
            return x;
        }
        if (a[x].key != a[y].key)
        {
            return a[x].key < a[y].key ? x : y;
        }
        return a[x].val < a[y].val ? x : y;
    }
    void PushUp(int p)
    {
        if (tr[ls].now <= tr[rs].now)
        {
            tr[p].now = tr[ls].now;
            tr[p].from = tr[ls].from;
        }
        else
        {
            tr[p].now = tr[rs].now;
            tr[p].from = tr[rs].from;
        }
        tr[p].mn = mim(tr[ls].mn, tr[rs].mn);
    }
    void PushDown(int p)
    {
        if (!tr[p].lazy)
        {
            return;
        }
        tr[ls].lazy += tr[p].lazy;
        tr[rs].lazy += tr[p].lazy;
        tr[ls].now += tr[p].lazy;
        tr[rs].now += tr[p].lazy;
        tr[p].lazy = 0;
    }
    void Build(int p, int l, int r)
    {
        if (l == r)
        {
            tr[p].val = a[l].val;
            tr[p].now = tr[p].key = a[l].key;
            tr[p].from = l;
            tr[p].mn = l;
            return;
        }
        int mid = (l + r) >> 1;
        Build(ls, l, mid);
        Build(rs, mid + 1, r);
        PushUp(p);
    }
    void Modify(int p, int l, int r, int pos)
    {
        if (l == r)
        {
            tr[p].key = 0x3f3f3f3f;
            tr[p].now = 0x3f3f3f3f;
            tr[p].mn = -1;
            return;
        }
        PushDown(p);
        int mid = (l + r) >> 1;
        if (pos <= mid)
        {
            Modify(ls, l, mid, pos);
        }
        else
        {
            Modify(rs, mid + 1, r, pos);
        }
        PushUp(p);
    }
    void Modify(int p, int l, int r, int L, int R)
    {
        if (L > R)
        {
            return;
        }
        if (L <= l && r <= R)
        {
            --tr[p].lazy;
            --tr[p].now;
            return;
        }
        PushDown(p);
        int mid = (l + r) >> 1;
        if (L <= mid)
        {
            Modify(ls, l, mid, L, R);
        }
        if (R > mid)
        {
            Modify(rs, mid + 1, r, L, R);
        }
        PushUp(p);
    }
    int Query(int p, int l, int r, int L, int R)
    {
        if (L > R)
        {
            return -1;
        }
        if (L <= l && r <= R)
        {
            return tr[p].mn;
        }
        PushDown(p);
        int mid = (l + r) >> 1, ans = -1;
        if (L <= mid)
        {
            ans = mim(ans, Query(ls, l, mid, L, R));
        }
        if (R > mid)
        {
            ans = mim(ans, Query(rs, mid + 1, r, L, R));
        }
        PushUp(p);
        return ans;
    }
} T;

int pre[maxn], nxt[maxn];

int main()
{
    #ifndef DEBUG
    freopen("block.in", "r", stdin);
    freopen("block.out", "w", stdout);
    #endif
    n = read();
    for (int i = 1; i <= n; ++i)
    {
        a[i].key = read();
        a[i].val = read();
    }
    sort(a + 1, a + n + 1, cmp);
    ll ans = 1;
    int tot = 1;
    for (int i = 1; i <= n; ++i)
    {
        if (a[i].val == a[i - 1].val)
        {
            ans = ans * min(i, a[i].key + tot) % mod;
            ++tot;
        }
        else
        {
            ans = ans * min(i, a[i].key) % mod;
            tot = 1;
        }
    }
    printf("%lld\n", ans);
    sort(a + 1, a + n + 1, cmp2);
    for (int i = 1; i <= n; ++i)
    {
        if (a[i].val == a[i - 1].val)
        {
            pre[i] = pre[i - 1];
        }
        else
        {
            pre[i] = i - 1;
            nxt[i - 1] = i;
        }
    }
    for (int i = n; i; --i)
    {
        if (!nxt[i])
        {
            nxt[i] = nxt[i + 1];
        }
    }
    nxt[n] = n;
    T.Build(1, 1, n);
    for (int i = 1; i <= n; ++i)
    {
        int tmp;
        if (T.tr[1].now == 1)
        {
            tmp = T.Query(1, 1, n, 1, nxt[T.tr[1].from]);
        }
        else
        {
            tmp = T.tr[1].mn;
        }
        printf("%d %d\n", a[tmp].key, a[tmp].val);
        T.Modify(1, 1, n, tmp);
        T.Modify(1, 1, n, 1, pre[tmp]);
    }
}

T3. 隨機化即可(霧)

#include <cstdio>
#include <cstring>
#include <cctype>
#include <iostream>
#include <sstream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <map>
#include <deque>
#include <queue>
#include <bitset>
#include <list>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

int read()
{
    int x = 0;
    char c;
    bool f = 0;
    while (!isdigit(c = getchar()))
    {
        if (c == '-')
        {
            f = 1;
        }
    }
    do
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
    } while (isdigit(c = getchar()));
    if (f)
    {
        return -x;
    }
    return x;
}

const int maxn = 1e3 + 10, maxe = 2e3 + 10;

struct Graph
{
    int head[maxn], len;
    int nxt[maxe << 1], to[maxe << 1], dis[maxe << 1];
    void Ins(int u, int v, int d)
    {
        to[++len] = v;
        nxt[len] = head[u];
        dis[len] = d;
        head[u] = len;
    }
} G;

int n, m, tot;

ull dis1[maxn], disn[maxn];
bool vis[maxn];

struct data
{
    ull dis;
    int u;
    data(ull a, int b)
    {
        dis = a;
        u = b;
    }
    bool operator < (const data &b) const
    {
        return dis > b.dis;
    }
};

ull x;

void Dijkstra(int s, ull *dis)
{
    priority_queue<data> q;
    memset(vis, 0, sizeof vis);
    dis[s] = 0;
    q.push(data(0, s));
    while (!q.empty())
    {
        int u = q.top().u;
        q.pop();
        if (vis[u])
        {
            continue;
        }
        vis[u] = 1;
        for (int i = G.head[u]; i; i = G.nxt[i])
        {
            int v = G.to[i];
            if (G.dis[i] == -1)
            {
                if (dis[v] > dis[u] + x)
                {
                    dis[v] = dis[u] + x;
                    q.push(data(dis[v], v));
                }
            }
            else
            {
                if (dis[v] > dis[u] + G.dis[i])
                {
                    dis[v] = dis[u] + G.dis[i];
                    q.push(data(dis[v], v));
                }
            }
        }
    }
}

bool ok[maxn];

ull rand(ull l, ull r)
{
    return 1ull * rand() * rand() % (r - l + 1) + l;
}

void Test()
{
    memset(dis1, 0x3f, sizeof dis1);
    memset(disn, 0x3f, sizeof disn);
    Dijkstra(1, dis1);
    Dijkstra(n, disn);
    for (int i = 1; i <= n; ++i)
    {
        if (dis1[i] + disn[i] == dis1[n])
        {
            ok[i] = 1;
        }
    }
}

int main()
{
    srand(time(0));
    #ifndef DEBUG
    freopen("graph.in", "r", stdin);
    freopen("graph.out", "w", stdout);
    #endif
    n = read(), m = read();
    ull MAX = 0;
    for (int i = 1; i <= m; ++i)
    {
        int u = read(), v = read(), d = read();
        if (d == -1)
        {
            ++tot;
        }
        if (d != -1)
        {
            MAX = max(MAX, 1ull * d);
        }
        G.Ins(u, v, d);
        G.Ins(v, u, d);
    }
    if (n < 1000) 
    {
        for (x = 0; x <= 100000; x += 4)
        {
            Test();
        }
    }
    else 
    { 
        x = 0;
        Test();
        for (ull l = 1; l <= 1e6; l += 1e4)
        {
            for (int j = 1; j <= 5; ++j)
            {
                x = rand(l, l + 1e4 - 1);
                Test();
            }
        }
        for (ull l = 1e6; l <= MAX; l += 1e7)
        {
            for (int j = 1; j <= 5; ++j)
            {
                x = rand(l, l + 1e7 - 1);
                Test();
            }
        }
        x = 1e14;
        Test();
    }
    for (int i = 1; i <= n; ++i)
    {
        if (ok[i])
        {
            putchar('1');
        }
        else
        {
            putchar('0');
        }
    }
    putchar('\n');
}