OUC_2014 Spring Training 省赛组队训练赛 #1总结

A线段树或者树状数组,离线处理,hash,数组开大些 hdu3333

#include <iostream>
#include <cstdio>
#include <string.h>
#include <map>

using namespace std;

#define MAXN 300000 + 10

map <__int64, int> hash;
int n, m;
__int64 val[MAXN], ans[MAXN], c[MAXN];

struct Node
{
    int l, r, index;
}q[MAXN];

__int64 lowbit(int x)
{
    return x & (-x);
}

__int64 sum(int n)
{
    __int64 sum = 0;
    while (n > 0)
    {
        sum += c[n];
        n -= lowbit(n);
    }

    return sum;
}

void change(int i, __int64 x)
{
    while (i <= n)
    {
        c[i] = c[i] + x;
        i += lowbit(i);
    }
}

bool cmp(Node a, Node b)
{
    return a.r < b.r;
}

void input()
{
    int t;

    cin >> t;

    while (t--)
    {
        scanf("%d", &n);
        hash.clear();
        memset(c, 0, sizeof(c));

        for (int i = 1; i <= n; i++)
        {
            scanf("%I64d", &val[i]);
        }

        scanf("%d", &m);

        for (int i = 0; i < m; i++)
        {
            scanf("%d %d", &q[i].l, &q[i].r);
            q[i].index = i;
        }

        sort(q, q + m, cmp);

        for (int i = 0, pos = 1; i < m; i++)
        {
            while (pos <= n && pos <= q[i].r)
            {
                if (hash[val[pos]])
                {
                    change(hash[val[pos]], -val[pos]);
                }
                change(pos, val[pos]);
                hash[val[pos]] = pos;
                pos++;
            }
            ans[q[i].index] = sum(q[i].r) - sum(q[i].l - 1);
        }

        for (int i = 0; i < m; i++)
        {
            printf("%I64d\n",ans[i]);
        }
    }
}

int main()
{
    input();
    return 0;
}

B题 略

C题二分图匹配求最大独立集,二分图中最大独立集 = 节点数 - 最大匹配数 hdu3335

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <string>

using namespace std;

#define MAXN 1000 * 10

int n;
bool vis[MAXN];
int match[MAXN];
__int64 node[MAXN];

struct Edge
{
    int u, v, next;
}edge[1000 * MAXN];

int head[MAXN], e;

void add(int u, int v)
{
    edge[e].v = v;
    edge[e].next = head[u];
    head[u] = e++;
}

void init()
{
    e = 0;
    memset(head, -1, sizeof(head));
    memset(match, -1, sizeof(match));
}


bool dfs(int u)
{
    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].v;
        if (!vis[v])
        {
            vis[v] = true;
            if (match[v] == -1 || dfs(match[v]))
            {
                match[v] = u;
                return true;
            }
        }
    }
    return false;
}

int solve()
{
    int res = 0;

    for (int i = 0; i < n; i++)
    {
        memset(vis, false, sizeof(vis));

        if (dfs(i))
        {
            res++;
        }
    }

    return res;
}

void input()
{
    int t;

    cin >> t;

    while (t--)
    {
        init();

        scanf("%d", &n);

        for (int i = 0; i < n; i++)
        {
            scanf("%I64d", &node[i]);
        }

        sort(node, node + n);
        int temp = 0;

        for (int i = 1; i < n; i++)
        {
            if (node[temp] != node[i])
            {
                node[++temp] = node[i];
            }
        }
        n = temp + 1;

        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                if (node[j] % node[i] == 0)
                {
                    add(i, j);
                }
            }
        }

        cout << n - solve() << endl;
    }
}

int main()
{
    input();
    return 0;
}

D题 Kmp + dp

#include <iostream>
#include <string.h>

using namespace std;

#define MAXN 200000 + 100

int next[MAXN];
string str;

void getN()
{
    next[0] = -1;

    for (int i = 1, j = -1; i < str.length(); i++)
    {
        while (j >= 0 && str[i] != str[j + 1])
        {
            j = next[j];
        }

        if (str[i] == str[j + 1])
        {
            j++;
        }

        next[i] = j;
    }
}

int c[MAXN];

void input()
{
    int cases, n;
    long long sum = 0;
    cin >> cases;

    while (cases--)
    {
        sum = 0;
        memset(c, 0, sizeof(c));
        cin >> n;
        cin >> str;
        getN();

        for (int i = 0; i < n; i++)
        {
            next[i]++;
        }

        for (int i = 1; i <= n; i++)
        {
            c[i] = (c[next[i - 1]] + 1) % 10007;
            sum = (sum + c[i]) % 10007;
        }

        cout << sum << endl;
    }
}

int main()
{
    input();
    return 0;
}

EF题 略

G题 最短路 + dp 有重边

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <string>

using namespace std;

#define MAXN 150
#define inf 100000000

int c[MAXN][MAXN];
int val[MAXN];
int dp[10000 * MAXN];

void input()
{
    int t;
    int u, v, w, n, m;

    cin >> t;

    while (t--)
    {
        scanf("%d %d", &n, &m);
        memset(dp, 0, sizeof(dp));

        for (int i = 0; i <= n; i++)
        {
            for (int j = 0; j <= n; j++)
            {
                c[i][j] = (i == j ? 0 : inf);
            }
        }

        for (int i = 0; i < m; i++)
        {
            scanf("%d %d %d", &u, &v, &w);
            c[u][v] = c[v][u]= min(c[u][v], w);
        }

        for (int k = 0; k <= n; k++)
        {
            for (int i = 0; i <= n; i++)
            {
                for (int j = 0; j <= n; j++)
                {
                    if (c[i][k] + c[k][j] < c[i][j])
                    {
                        c[i][j] = c[i][k] + c[k][j];
                    }
                }
            }
        }

        int sum = 0, v = 0;

        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &val[i]);
            sum += val[i];
            if (c[0][i] != inf)
            {
                v += c[0][i];
            }
        }

        sum /= 2;

        for (int i = 1; i <= n; i++)
        {
            if (c[0][i] != inf)
            for (int j = v; j >= c[0][i]; j--)
            {
                dp[j] = max(dp[j], dp[j - c[0][i]] + val[i]);
            }
        }

        bool ok = false;

        for (int i = 1; i <= v; i++)
        {
            if (dp[i] > sum)
            {
                cout << i << endl;
                ok = true;
                break;
            }
        }

        if (!ok)
        {
            cout << "impossible" << endl;
        }
    }
}

int main()
{
    input();
    return 0;
}


I题ac自动机 + dp

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <string>
#include <queue>

using namespace std;

#define MAXN 50 + 10
#define MAXNODE 500 + 10

char c[MAXN], str[MAXN];
struct Trie
{
    int next[MAXNODE][4], fail[MAXNODE];
    int ends[MAXNODE];
    int root, L;

    int newnode()
    {
        for (int i = 0; i < 4; i++)
        {
            next[L][i] = -1;
        }
        ends[L++] = 0;
        return L - 1;
    }

    void init()
    {
        L = 0;
        root = newnode();
    }

    int getch(char ch)
    {
        if (ch == 'A') return 0;
        if (ch == 'C') return 1;
        if (ch == 'G') return 2;
        if (ch == 'T') return 3;
    }

    void inserts(char *ch)
    {
        int len = strlen(ch);
        int now = root;

        for (int i = 0; i < len; i++)
        {
            if (next[now][getch(ch[i])] == -1)
            {
                next[now][getch(ch[i])] = newnode();
            }
            now = next[now][getch(ch[i])];
        }
        ends[now]++;
    }

    void build()
    {
        queue <int> Q;
        fail[root] = root;
        for (int i = 0; i < 4; i++)
        {
            if (next[root][i] == -1)
            {
                next[root][i] = root;
            }
            else
            {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        }

        while (!Q.empty())
        {
            int now = Q.front();
            Q.pop();

            ends[now] += ends[fail[now]];
            for (int i = 0; i < 4; i++)
            {
                if (next[now][i] == -1)
                {
                    next[now][i] = next[fail[now]][i];
                }
                else
                {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
            }
        }
    }

    int dp[MAXNODE][11 * 11 * 11 * 11 + 10];
    int bit[4];
    int num[4];

    int solve()
    {
        int len = strlen(str);
        memset(num, 0, sizeof(num));

        for (int i = 0; i < len; i++)
        {
            num[getch(str[i])]++;
        }
        bit[0] = (num[1] + 1) * (num[2] + 1) * (num[3] + 1);
        bit[1] = (num[2] + 1) * (num[3] + 1);
        bit[2] = (num[3] + 1);
        bit[3] = 1;

        memset(dp, -1, sizeof(dp));
        dp[root][0] = 0;

        for (int a = 0; a <= num[0]; a++)
        {
            for (int b = 0; b <= num[1]; b++)
            {
                for (int c = 0; c <= num[2]; c++)
                {
                    for (int d = 0; d <= num[3]; d++)
                    {
                        int s = a * bit[0] + b * bit[1] + c * bit[2] + d * bit[3];

                        for (int i = 0; i < L; i++)
                        {
                            if (dp[i][s] >= 0)
                            for (int k = 0; k < 4; k++)
                            {
                                if (k == 0 && a == num[0])continue;
                                if (k == 1 && b == num[1])continue;
                                if (k == 2 && c == num[2])continue;
                                if (k == 3 && d == num[3])continue;
                                dp[next[i][k]][s + bit[k]] = max(dp[next[i][k]][s + bit[k]],dp[i][s] + ends[next[i][k]]);
                            }
                        }
                    }
                }
            }
        }

        int ans = 0;
        int st = num[0] * bit[0] + num[1] * bit[1] + num[2] * bit[2] + num[3] * bit[3];

        for (int i = 0; i < L; i++)
        {
            ans = max(ans, dp[i][st]);
        }

        cout << ans << endl;
    }
}ac;

void input()
{
    int n, cases = 0;
    while (cin >> n, n)
    {
        ac.init();
        for (int i = 0; i < n; i++)
        {
            scanf("%s", c);
            ac.inserts(c);
        }

        ac.build();
        scanf("%s", str);
        cout << "Case " << ++cases << ": ";
        ac.solve();
    }
}

int main()
{
    input();
    return 0;
}

J题 是否所给有向图中存在环 floyd求传递闭包,拓扑排序,tarjan求联通分量都可以解决

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <string>

using namespace std;

#define MAXN 200

int c[MAXN][MAXN];

void input()
{
    int n, m, u, v;

    while (cin >> n >> m, n)
    {
        memset(c, 0, sizeof(c));

        for (int i = 0; i < m; i++)
        {
            scanf("%d %d", &u, &v);
            c[u][v] = 1;
        }
        
        for (int k = 0; k < n; k++)
        {
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (c[i][k] && c[k][j])
                    {
                        c[i][j] = 1;
                    }
                }
            }
        }

        bool ok = true;

        for (int i = 0; i < n; i++)
        {
            if (c[i][i])
            {
                ok = false;
                break;
            }
        }

        cout << (ok ? "YES" : "NO") << endl;
    }
}

int main()
{
    input();
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值