• (4.17~4.23)


    [POJ 3417] Network

    LCA + 树上差分

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 1e5+50;
    typedef long long ll;
    ///加边
    int cnt, h[maxn];
    struct edge
    {
        int to, pre, v;
    } e[maxn << 1];
    void init()
    {
        cnt = 0;
        memset(h, 0, sizeof(h));
    }
    void add(int from, int to, int v)
    {
        cnt++;
        e[cnt].pre = h[from]; ///5-->3-->1-->0
        e[cnt].to = to;
        e[cnt].v = v;
        h[from] = cnt;
    }
    ///LCA
    int dist[maxn];
    int dep[maxn];
    int anc[maxn][33]; ///2分的父亲节点
    void dfs(int u, int fa)
    {
        for(int i = h[u]; i; i = e[i].pre)
        {
            int v = e[i].to;
            if(v == fa) continue;
            dist[v] = dist[u] + e[i].v;
            dep[v] = dep[u] + 1;
            anc[v][0] = u;
            dfs(v, u);
        }
    }
    void LCA_init(int n)
    {
        for(int j = 1; (1 << j) < n; j++)
            for(int i = 1; i <= n; i++) if(anc[i][j-1])
            anc[i][j] = anc[anc[i][j-1]][j-1];
    }
    int LCA(int u, int v)
    {
        int log;
        if(dep[u] < dep[v]) swap(u, v);
        for(log = 0; (1 << log) < dep[u]; log++);
        for(int i = log; i >= 0; i--)
            if(dep[u] - (1 << i) >= dep[v]) u = anc[u][i];
        if(u == v) return u;
        for(int i = log; i >= 0; i--)
            if(anc[u][i] && anc[u][i] != anc[v][i])
                u = anc[u][i], v = anc[v][i];
        return anc[u][0];
    }
    int w[maxn];
    int sum[maxn];
    int dfs2(int u, int fa)
    {
        sum[u] += w[u];
        for(int i = h[u]; i; i = e[i].pre)
        {
            int v = e[i].to;
            if(v == fa) continue;
            sum[u] += dfs2(v, u);
        }
        return sum[u];
    }
    int main()
    {
        init();
        int n, m; scanf("%d %d", &n, &m);
        for(int i = 1; i < n; i++)
        {
            int u, v; scanf("%d %d", &u, &v);
            add(u, v, 1), add(v, u, 1);
        }
        dfs(1, -1);
        LCA_init(n);
        memset(w, 0, sizeof(w));
        for(int i = 1; i <= m; i++)
        {
            int u, v; scanf("%d %d", &u ,&v);
            w[u] += 1, w[v] += 1;
           // printf("%d
    ", LCA(u, v));
            w[LCA(u, v)] += -2;
        }
        dfs2(1, -1);
        /*for(int i = 1; i <= n; i++)
        {
            printf("%d
    ", sum[i]);
        }*/
        int ans = 0;
        for(int i = 2; i <= n; i++)
        {
            if(sum[i] == 0) ans += m;
            if(sum[i] == 1) ans++;
        }
        printf("%d
    ", ans);
        return 0;
    }
    Code

    Destruction of a Tree

    各种剪枝。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 50;
    vector<int> g[maxn];
    int in[maxn];
    int vis[maxn];
    vector<int> ans;
    void dfs(int u, int fa, int flag)
    {
        if(flag == 0)
        {
            for(int i = 0; i < g[u].size(); i++)
            {
                int v = g[u][i];
                if(v == fa) continue;
                dfs(v, u, 0);
            }
        }
        if(in[u] != 0 && (in[u] % 2 == 0))
        {
            if(!vis[u]) ans.push_back(u), vis[u] = 1;
            for(int i = 0; i < g[u].size(); i++)
            {
                int v = g[u][i];
                if(flag == 1 && v == fa) continue;
    
    
                if(in[u] > 0)in[u]--;
                if(in[v] > 0)
                {
                    in[v]--;
                    if(in[v] == 0 && (!vis[v])) ans.push_back(v), vis[v] = 1;
                }
                if(v == fa) continue;
                if(in[v] != 0 && (in[v] % 2 == 0)) dfs(v, u, 1);
            }
        }
    }
    int main()
    {
        int n; scanf("%d", &n);
        int fa = 0;
        memset(in, 0, sizeof(in));
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= n; i++)
        {
            int x; scanf("%d", &x);
            if(!x) fa = i;
            else g[x].push_back(i), g[i].push_back(x), in[i]++, in[x]++;
        }
        dfs(fa, -1, 0);
        int cnt = 0;
        for(int i = 1; i <= n; i++) if(in[i] == 0) cnt++;
        if(cnt == n)
        {
            printf("YES
    ");
            for(int i = 0; i < ans.size(); i++) printf("%d
    ", ans[i]);
            if(n == 1) printf("1
    ");
        }
        else printf("NO
    ");
    
        return 0;
    }
    Code

    BZOJ 4195

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e6 + 50;
    int pre[maxn * 2];
    int x[maxn * 2];
    struct node
    {
        int l, r, w;
        friend bool operator < (node A, node B)
        {
            if(A.w != B.w)return A.w > B.w;
            else return A.l < B.l;
        }
    };
    node cnt[maxn];
    int Find(int x)
    {
        return x == pre[x] ? x : pre[x] = Find(pre[x]);
    }
    void merge1(int x,int y)
    {
        pre[Find(x)] = Find(y);
    }
    int main()
    {
        int T; scanf("%d", &T);
        while(T--)
        {
            for(int i = 0; i < maxn * 2; i++) pre[i] = i;
            int num = 0;
            int n; scanf("%d", &n);
            for(int i = 1; i <= n; i++)
            {
                scanf("%d %d %d", &cnt[i].l, &cnt[i].r, &cnt[i].w);
                x[num++] = cnt[i].l, x[num++] = cnt[i].r;
            }
            sort(x, x + num);
            num = unique(x, x + num) - x;
            for(int i = 1; i <= n; i++)
            {
                cnt[i].l = lower_bound(x, x + num, cnt[i].l) - x;
                cnt[i].r = lower_bound(x, x + num, cnt[i].r) - x;
            }
            sort(cnt + 1, cnt + n + 1);
            int flag = 0;
            for(int i = 1; i <= n; i++)
            {
                if(cnt[i].w)
                {
                    merge1(cnt[i].l, cnt[i].r);
                }
                else
                {
                    if(Find(cnt[i].l) == Find(cnt[i].r))
                    {
                        flag = 1;
                        break;
                    }
                }
            }
            if(flag) printf("NO
    ");
            else printf("YES
    ");
        }
        return 0;
    }
    /*
    2
    3
    1 2 0
    2 3 0
    1 3 1
    */
    Code

     POJ 1456

    优先队列

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    priority_queue <int, vector<int>, greater<int> > q;
    const int maxn = 1e4 + 50;
    vector<int> pro[maxn];
    int main()
    {
        int n;
        while(scanf("%d", &n) != EOF)
        {
            for(int i = 1; i < maxn; i++) pro[i].clear();
            int p, d;
            for(int i = 1; i <= n; i++)
            {
                scanf("%d %d", &p, &d);
                pro[d].push_back(p);
            }
            for(int i = 1; i <= 10000; i++) sort(pro[i].begin(), pro[i].end());
            for(int i = 1; i <= 10000; i++)
            {
                int tmp = i;
                for(int j = pro[i].size() - 1; j >= 0 && tmp >= 1; j--, tmp--)
                {
                     q.push(pro[i][j]);
                }
                while(q.size() > i) q.pop();
            }
            int sum = 0;
            while(!q.empty())
            {
                sum += q.top();
                q.pop();
            }
            printf("%d
    ", sum);
        }
        return 0;
    }
    /*
    2
    3
    1 2 0
    2 3 0
    1 3 1
    */
    Code

    贪心 + 并查集

    #include <bits/stdc++.h>
    using namespace std;
    struct node
    {
        int p, d;
        friend bool operator < (node A, node B)
        {
            return A.p > B.p;
        }
    };
    const int maxn = 1e4 + 50;
    node cnt[maxn];
    int pre[maxn];
    int Find(int x)
    {
        return x == pre[x] ? x : pre[x] = Find(pre[x]);
    }
    void merge1(int x, int y)
    {
        pre[Find(x)] = Find(y);
    }
    int main()
    {
        int n;
        while(scanf("%d", &n) != EOF)
        {
            for(int i = 1; i <= 10000; i++) pre[i] = i;
            for(int i = 1; i <= n; i++) scanf("%d %d", &cnt[i].p, &cnt[i].d);
            sort(cnt + 1, cnt + n + 1);
            int ans = 0;
            for(int i = 1; i <= n; i++)
            {
                int fa = Find(cnt[i].d);
                if(fa > 0) ans += cnt[i].p, pre[fa] = fa - 1;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    Code

     CODEVS 1540

    边带权并查集

    晚上睡觉的时候想,如果 2 --> 3,这样的链接在 4 后面,这样d[2] = 2, d[3] = 1, d[4]  = 0,如果反复查询2的话,会变成不断累加? 答案是不会的,因为2 -- > 4。d数组要全部初始化成0

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <vector>
    using namespace std;
    const int maxn  = 1e5;
    int pre[maxn * 2];
    struct node
    {
        int l, r, st;
    };
    node cur[maxn];
    int x[maxn * 2];
    int d[maxn * 2];
    int Find(int x)
    {
        if(x == pre[x]) return x;
        int root = Find(pre[x]);
        d[x] ^= d[pre[x]];
        return pre[x] = root;
    }
    int main()
    {
        int len, n;
        scanf("%d %d", &len, &n);
        int m = 0;
        memset(d, 0, sizeof(d));
        for(int i = 1; i <= n; i++)
        {
            char s[10];
            scanf("%d %d %s", &cur[i].l, &cur[i].r, s);
            cur[i].st = (s[0] == 'e' ? 0 : 1);
          //  printf("%d
    ", cur[i].st);
            x[m++] = cur[i].l - 1;
            x[m++] = cur[i].r;
        }
        sort(x, x + m);
        m = unique(x, x + m) - x;
        for(int i = 0; i <= m; i++) pre[i] = i;
        for(int i = 1; i <= n; i++)
        {
            cur[i].l = lower_bound(x, x + m, cur[i].l - 1) - x;
            cur[i].r = lower_bound(x, x + m, cur[i].r) - x;
            int p = Find(cur[i].l);
            int q = Find(cur[i].r);
            if(p == q)
            {
            //    printf("dasda
    ");
                if((d[cur[i].l] ^ d[cur[i].r]) == cur[i].st) continue;
                printf("%d
    ", i - 1);
                return 0;
            }
            else pre[p] = q, d[p] = d[cur[i].l] ^ d[cur[i].r] ^ cur[i].st;
        }
        printf("%d
    ", n);
        return 0;
    }
    /*
    10
    4
    2 5 even
    6 8 odd
    3 7 odd
    2 8 even
    */
    Code

     POJ 1733 

    边带权并查集:

    要能看出它的传递性:

    sum[l,r]表示l,r之间1的个数

    如果sum[l,r]为奇数,那么sum[r]与sum[l-1]奇偶性不同;

    如果sum[l,r]为偶数,那么sum[r]与sum[l-1]奇偶性相同。

    借助传递性,比如sum[2,5] 是 even, sum[1]与sum[5]相同,sum[6,8]是odd,sum[5]与sum[8]不同,所以sum[1]与sum[8]不同。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn  = 1e4 + 50;
    int pre[maxn * 2];
    struct node
    {
        int l, r, st;
    };
    node cur[maxn];
    int x[maxn * 2];
    int d[maxn * 2];
    int Find(int x)
    {
        if(x == pre[x]) return x;
        int root = Find(pre[x]);
        d[x] ^= d[pre[x]];
        return pre[x] = root;
    }
    int main()
    {
        int len, n;
        scanf("%d %d", &len, &n);
        int m = 0;
        for(int i = 1; i <= n; i++)
        {
            char s[10];
            scanf("%d %d %s", &cur[i].l, &cur[i].r, s);
            cur[i].st = (s[0] == 'e' ? 0 : 1);
          //  printf("%d
    ", cur[i].st);
            x[m++] = cur[i].l;
            x[m++] = cur[i].r;
        }
        sort(x, x + m);
        m = unique(x, x + m) - x;
        for(int i = 0; i <= m; i++) pre[i] = i;
        for(int i = 1; i <= n; i++)
        {
            cur[i].l = lower_bound(x, x + m, cur[i].l) - x;
            cur[i].r = lower_bound(x, x + m, cur[i].r) - x;
            int p = Find(cur[i].l - 1);
            int q = Find(cur[i].r);
            if(p == q)
            {
            //    printf("dasda
    ");
                if((d[cur[i].l - 1] ^ d[cur[i].r]) == cur[i].st) continue;
                printf("%d
    ", i - 1);
                return 0;
            }
            else pre[p] = q, d[p] = d[cur[i].l - 1] ^ d[cur[i].r] ^ cur[i].st;
        }
        printf("%d
    ", n);
        return 0;
    }
    /*
    10
    4
    2 5 even
    6 8 odd
    3 7 odd
    2 8 even
    */
    Code

     Mahmoud and a Dictionary

    和上题一样。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 50;
    map<string, int> mp;
    int pre[maxn];
    int d[maxn];
    int Find(int x)
    {
        if(x == pre[x]) return x;
        int root = Find(pre[x]);
        d[x] ^= d[pre[x]];
        return pre[x] = root;
    }
    int main()
    {
        int n, m, q; scanf("%d %d %d", &n, &m, &q);
        char s[25];
        string tmp;
        for(int i = 1; i <= n; i++) scanf("%s", s), tmp = s, mp[s] = i, pre[i] = i, d[i] = 0;
        for(int i = 1; i <= m; i++)
        {
            int t;
            char s1[25], s2[25];
            scanf("%d %s %s", &t, s1, s2);
            int x = mp[s1], y = mp[s2];
            int ans = t == 1 ? 0 : 1;
            int p = Find(x);
            int q = Find(y);
            if(p == q)
            {
                if((d[x] ^ d[y]) == ans) printf("YES
    ");
                else printf("NO
    ");
            }
            else
            {
                pre[p] = q;
                d[p] = d[x] ^ d[y] ^ ans;
                printf("YES
    ");
            }
        }
        for(int i = 1; i <= q; i++)
        {
            char s1[25], s2[25];
            scanf("%s %s", s1, s2);
            int x = mp[s1], y = mp[s2];
            int p = Find(x);
            int q = Find(y);
            if(p != q) printf("3
    ");
            else
            {
                printf("%d
    ", (d[x] ^ d[y]) == 1 ? 2 : 1);
            }
        }
        return 0;
    }
    Code

     今天打完ningxia,听他们说最近有三道差不多的FFT,我看了三道题,然后看了两个题解,还是不太懂为啥那样做,我还是先把之前的FFT补补吧。

     

     

  • 相关阅读:
    设置MySQL的字符编码
    数据库面试题
    java.lang.IncompatibleClassChangeError: Implementing class
    下载SpringJar包
    使用命令wsimport构建WebService客户端
    java读取.properties配置文件的几种方法
    ELK5.X使用X-Pack配置密码
    Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock'
    MySQL常用命令
    XPath常用定位节点元素语句总结
  • 原文地址:https://www.cnblogs.com/littlepear/p/8867452.html
Copyright © 2020-2023  润新知