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

来源:互联网 发布:五常知乎 编辑:程序博客网 时间:2024/05/18 02:26

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

#include <iostream>#include <cstdio>#include <string.h>#include <map>using namespace std;#define MAXN 300000 + 10map <__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 * 10int 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 + 100int 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 100000000int 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 + 10char 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 200int 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;}



0 0
原创粉丝点击