Assignment 3: Data Structures

  • 2418 Hardwood Species (1)

  • 1330 Nearest Common Ancestors (3)

  • 3367 Expressions (3)

  • 1984 Navigation Nightmare (5)

  • 1785 Binary Search Heap Construction (5)

  • 1988 Cube Stacking (6)

  • 1703 Find them, Catch them (6)

  • 2274 The Race (6)

  • 3321 Apple Tree (6)

  • 1177 Picture (7, challenge problem)

  • 1195 Mobile phones (8, challenge problem)

  • 2750 Potted Flower (9, challenge problem)


    poj1330

    最近公共祖先的Tarjan离线算法

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<iostream>
    #include<iterator>
    using namespace std;
    int n, a, b;
    int fa[10010];
    vector <int> adj[10010];
    
    int find(int x) {
        if (x != fa[x])
            fa[x] = find(fa[x]);
        return fa[x];
    }
    
    void merge(int x, int y) {
        x = find(x);
        y = find(y);
        fa[x] = y;
    }
    int ok, rd[10010];
    
    void dfs(int r) {
        int u, v;
        vector<int> ::iterator it;
        fa[r] = r;
        for (it = adj[r].begin(); it != adj[r].end(); ++it) {
            v = *it;
          //  printf("u=%d v=%d\n", r, v);
            if (v == a && fa[b]) {
                printf("%d\n", find(b));
                ok = 1;
            } else if (v == b && fa[a]) {
                printf("%d\n", find(a));
                ok = 1;
            }
            if (ok)
                return;
            dfs(v);
            fa[v] = r;
        }
    }
    
    int main() {
        int T, i, j, u, v;
        scanf("%d", &T);
        while (T--) {
            scanf("%d", &n);
            memset(fa, 0, sizeof (fa));
            for (i = 1; i <= n; ++i)
                adj[i].clear();
            memset(rd, 0, sizeof (rd));
            for (i = 1; i < n; ++i) {
                scanf("%d%d", &u, &v);
                adj[u].push_back(v);
                ++rd[v];
            }
            scanf("%d%d", &a, &b);
            ok = 0;
            for (i = 1; i <= n; ++i)
                if (!rd[i])
                    dfs(i);
        }
        return 0;
    }

    poj1984

    并查集的路径压缩

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    
    typedef struct S {
        int u, v, id, I;
    } ASK;
    ASK ask[10010];
    int ans[10010];
    
    bool cmp(ASK a, ASK b) {
        return a.I < b.I;
    }
    
    typedef struct G {
        int u, v, x, y;
    } REL;
    REL rel[40010];
    int n, m, q;
    int fa[40010], rankx[40010], ranky[40010];
    
    int find(int x) {
        if (x != fa[x]) {
            int q = fa[x];
            fa[x] = find(fa[x]);
            rankx[x] += rankx[q];
            ranky[x] += ranky[q];
        }
        return fa[x];
    }
    
    void merge(int i) {
        int a, b;
        a = find(rel[i].u);
        b = find(rel[i].v);
     //   printf("i=%d u=%d v=%d a=%d b=%d\n", i, rel[i].u, rel[i].v, a, b);
        if (a != b) {
            fa[a] = b;
            rankx[a] = rankx[rel[i].v] - rankx[rel[i].u] + rel[i].x;
            ranky[a] = ranky[rel[i].v] - ranky[rel[i].u] + rel[i].y;
        }
    }
    
    int ABS(int a) {
        return a < 0 ? -a : a;
    }
    
    void print() {
        for (int i = 1; i <= n; ++i) {
            printf("fa%d=%d ranx=%d ranky=%d\n", i, find(i), rankx[i], ranky[i]);
        }
    }
    
    int main() {
        int i, d, a, b;
        char ch[5];
        scanf("%d%d", &n, &m);
        for (i = 1; i <= n; ++i)
            fa[i] = i;
        for (i = 1; i <= m; ++i) {
            scanf("%d%d%d%s", &rel[i].u, &rel[i].v, &d, ch);
            if (ch[0] == 'N') rel[i].x = 0, rel[i].y = d;
            else if (ch[0] == 'S') rel[i].x = 0, rel[i].y = -d;
            else if (ch[0] == 'E') rel[i].x = d, rel[i].y = 0;
            else rel[i].x = -d, rel[i].y = 0;
        //    printf("rel%d: %d %d %d %d\n", i, rel[i].u, rel[i].v, rel[i].x, rel[i].y);
        }
        scanf("%d", &q);
        for (i = 0; i < q; ++i) {
            scanf("%d%d%d", &ask[i].u, &ask[i].v, &ask[i].I);
            ask[i].id = i;
        }
        sort(ask, ask + q, cmp);
        int p = 0;
        for (i = 1; i <= m;) {
            while (i == ask[p].I + 1) {
            //    printf("ask%d: u=%d v=%d I=%d\n", p, ask[p].u, ask[p].v, ask[p].I);
                a = find(ask[p].u);
                b = find(ask[p].v);
                if (a != b) {
                    ans[ask[p].id] = -1;
                } else {
                    ans[ask[p].id] = ABS(rankx[ask[p].u] - rankx[ask[p].v]) + ABS(ranky[ask[p].u] - ranky[ask[p].v]);
                }
                ++p;
                if (p == q)
                    goto L;
            }
            merge(i);
        //    print();
            ++i;
        }
        while (i == ask[p].I + 1) {
      //     printf("ask%d: u=%d v=%d I=%d\n", p, ask[p].u, ask[p].v, ask[p].I);
            a = find(ask[p].u);
            b = find(ask[p].v);
            if (a != b) {
                ans[ask[p].id] = -1;
            } else {
                ans[ask[p].id] = ABS(rankx[ask[p].u] - rankx[ask[p].v]) + ABS(ranky[ask[p].u] - ranky[ask[p].v]);
            }
            ++p;
            if (p == q)
                break;
        }
    L:
        for (i = 0; i < q; ++i)
            printf("%d\n", ans[i]);
        return 0;
    }

    poj1785

    手写堆

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<string>
    using namespace std;
    
    typedef struct S {
        char name[50];
        int p;
    }
    NODE;
    NODE node[50010];
    int L[50010], R[50010];
    
    void gao(int r) {
        printf("(");
        if (L[r] != -1)
            gao(L[r]);
        printf("%s/%d",node[r].name,node[r].p);
     //   cout << node[r].name << "/" << node[r].p;
        if (R[r] != -1)
            gao(R[r]);
        printf(")");
    }
    
    bool cmp(const NODE &a, const NODE &b) {
        return strcmp(a.name, b.name) < 0;
    }
    
    int main() {
        int n, i, r, t, l;
        while (scanf("%d", &n) != EOF && n) {
            r = 0;
            memset(L, -1, sizeof (L));
            memset(R, -1, sizeof (R));
            for (i = 0; i < n; ++i) {
                //    getline(cin, node[i].name, '/');
                //     scanf("%d", &node[i].p);
                scanf("%*[ ]%[^/]/%d", node[i].name, &node[i].p);
            //    printf("%s/%d\n",node[i].name,node[i].p);
            }
            sort(node, node + n, cmp);
            for (i = 1; i < n; ++i) {
                if (node[i].p > node[r].p) {
                    L[i] = r;
                    r = i;
                } else {
                    t = r;
                    while (node[i].p < node[t].p) {
                        if (R[t] == -1) {
                            R[t] = i;
                            goto G;
                        }
                        l = t;
                        t = R[t];
                    }
                    R[l] = i;
                    L[i] = t;
                }
    G:
                ;
            }
            gao(r);
            printf("\n");
        }
        return 0;
    }

    poj2274

    记录每辆车的前继和后继,优先队列每次取时刻最小的超车。

    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    #define maxn 250000
    int x[maxn + 10], v[maxn + 10];
    int cnt_v[110];
    long long ans;
    #define mod 1000000
    
    struct pass {
        int px, py, tx, ty, a, b;
    
        pass() {
        }
    
        pass(int ppx, int ppy, int ttx, int tty, int aa, int bb) : px(ppx), py(ppy), tx(ttx), ty(tty), a(aa), b(bb) {
        }
    
        bool operator>(const pass& temp)const {
            if ((long long) temp.ty * tx != (long long) ty * temp.tx)
                return (long long) temp.ty * tx > (long long) ty * temp.tx;
            return (long long) temp.py * px > (long long) py * temp.px;
        }
    } temp;
    priority_queue<pass, vector<pass>, greater<pass> > q;
    
    void gao(int a, int b) {
        q.push(pass(v[a] * x[b] - v[b] * x[a], v[a] - v[b], x[b] - x[a], v[a] - v[b], a, b));
    }
    int f[maxn + 10], b[maxn + 10];
    
    int main() {
        int n, i, j;
        while (scanf("%d", &n) != EOF) {
            ans = 0;
            memset(cnt_v, 0, sizeof (cnt_v));
            for (i = 0; i < n; ++i) {
                scanf("%d%d", &x[i], &v[i]);
                for (j = v[i] + 1; j < 100; ++j)
                    ans += cnt_v[j];
                cnt_v[v[i]]++;
            }
            printf("%lld\n", ans % mod);
            if (ans > 10000)
                ans = 10000;
            b[0] = -1;
            f[0] = 1;
            for (i = 1; i < n; ++i) {
                b[i] = i - 1;
                f[i] = i + 1;
                if (v[i - 1] > v[i]) {
                    gao(i - 1, i);
                }
            }
            f[n - 1] = -1;
            while (ans--) {
                temp = q.top();
                q.pop();
                if (f[temp.a] != temp.b || b[temp.b] != temp.a){
                    ++ans;
                    continue;
                }
                printf("%d %d\n", temp.a + 1, temp.b + 1);
                b[temp.b] = b[temp.a];
                b[temp.a] = temp.b;
                f[temp.a] = f[temp.b];
                f[temp.b] = temp.a;
                if (b[temp.b] != -1)
                    f[b[temp.b]] = temp.b;
                if (f[temp.a] != -1)
                    b[f[temp.a]] = temp.a;
                if (b[temp.b] != -1 && v[b[temp.b]] > v[temp.b])
                    gao(b[temp.b], temp.b);
                if (f[temp.a] != -1 && v[temp.a] > v[f[temp.a]])
                    gao(temp.a, f[temp.a]);
            }
            while (!q.empty())
                q.pop();
        }
        return 0;
    }

    poj1177

    扫面线求矩形面积并

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    
    struct EDGE {
        int l, r, h, f;
    
        EDGE() {
        }
    
        EDGE(int ll, int rr, int hh, int ff) : l(ll), r(rr), h(hh), f(ff) {
        }
    
        bool operator<(const EDGE &e) const {
            return h < e.h;
        }
    } edge[10010];
    
    int n, lm, rm, m;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define maxn (1<<16)
    int cnt[maxn], len[maxn], seg[maxn], lbd[maxn], rbd[maxn];
    int ans;
    
    void push_up(int l, int r, int rt) {
        if (cnt[rt]) {
            lbd[rt] = rbd[rt] = 1;
            len[rt] = r - l + 1;
            seg[rt] = 2;
        } else {
            if (l == r) {
                lbd[rt] = rbd[rt] = len[rt] = seg[rt] = 0;
            } else {
                lbd[rt] = lbd[rt << 1];
                rbd[rt] = rbd[rt << 1 | 1];
                len[rt] = len[rt << 1] + len[rt << 1 | 1];
                seg[rt] = seg[rt << 1] + seg[rt << 1 | 1];
                if (rbd[rt << 1] && lbd[rt << 1 | 1])
                    seg[rt] -= 2;
            }
        }
    }
    
    void update(int L, int R, int f, int l, int r, int rt) {
        if (L <= l && r <= R) {
            cnt[rt] += f;
            push_up(l, r, rt);
            return;
        }
        int m = (l + r) >> 1;
        if (L <= m) {
            update(L, R, f, lson);
        }
        if (R > m) {
            update(L, R, f, rson);
        }
        push_up(l, r, rt);
    }
    
    int main() {
        int i, a, b, c, d;
        scanf("%d", &n);
        lm = 10001, rm = -10001;
        for (i = 0; i < n; ++i) {
            scanf("%d%d%d%d", &a, &c, &b, &d);
            lm = min(lm, a), rm = max(rm, b - 1);
            edge[m++] = EDGE(a, b - 1, c, 1);
            edge[m++] = EDGE(a, b - 1, d, -1);
        }
        sort(edge, edge + m);
        int last = 0;
        for (i = 0; i < m; ++i) {
         //   printf("i=%d l=%d r=%d h%d f=%d\n", i, edge[i].l, edge[i].r, edge[i].h, edge[i].f);
            update(edge[i].l, edge[i].r, edge[i].f, lm, rm, 1);
        //    printf("seg=%d len=%d\n", seg[1], len[1]);
            ans += (edge[i + 1].h - edge[i].h) * seg[1];
            ans += abs(len[1] - last);
            last = len[1];
        }
        printf("%d\n", ans);
        return 0;
    }

    poj1195

    二维线段树,单点增加,成块求和

    #include<cstdio>
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    int sum[2100][2100];
    int n, core;
    
    void push_up2(int x, int rt) {
        sum[x][rt] = sum[x][rt << 1] + sum[x][rt << 1 | 1];
    }
    
    void update2(int x, int y, int c, int l, int r, int rt) {
    //    printf("xr=%d y=%d c=%d\n",x,y,c);
        if (y == l && y == r) {
            sum[x][rt] += c;
            return;
        }
        int m = (l + r) >> 1;
        if (y <= m)
            update2(x, y, c, lson);
        else
            update2(x, y, c, rson);
        push_up2(x, rt);
    }
    
    void update(int x, int y, int c, int l, int r, int rt) {
     //   printf("rt=%d l=%d r=%d\n",rt,l,r);
        update2(rt, y, c, 0, n - 1, 1);
        if (x == l && x == r) {
            return;
        }
        int m = (l + r) >> 1;
        if (x <= m)
            update(x, y, c, lson);
        else
            update(x, y, c, rson);
    }
    
    int query2(int x, int L, int R, int l, int r, int rt) {
        if (L <= l && r <= R)
            return sum[x][rt];
        int m = (l + r) >> 1, temp = 0;
        if (L <= m)
            temp += query2(x, L, R, lson);
        if (R > m)
            temp += query2(x, L, R, rson);
        return temp;
    }
    
    int query(int L, int R, int b, int t, int l, int r, int rt) {
        if (L <= l && r <= R)
            return query2(rt, b, t, 0, n - 1, 1);
        int m = (l + r) >> 1, temp = 0;
        if (L <= m)
            temp += query(L, R, b, t, lson);
        if (R > m)
            temp += query(L, R, b, t, rson);
        return temp;
    }
    
    int main() {
        int op, x, y, c, l, r, b, t;
        scanf("%d%d", &op, &n);
        while (scanf("%d", &op) != EOF && op < 3) {
            if (op == 1) {
                scanf("%d%d%d", &x, &y, &c);
                update(x, y, c, 0, n - 1, 1);
            } else {
                scanf("%d%d%d%d", &l, &b, &r, &t);
                if (l < 0)
                    l = 0;
                if (b < 0)
                    b = 0;
                if (r >= n)
                    r = n - 1;
                if (t >= n)
                    t = n - 1;
                printf("%d\n", query(l, r, b, t, 0, n - 1, 1));
            }
        }
        return 0;
    }

    poj2750

    线段树,单点更新,求成段最值。利用最大和最小的转换解决环的问题。

    #include<cstdio>
    #include<cstring>
    
    #define maxn (1<<18)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    int sum[maxn], smax[maxn], smin[maxn], lmax[maxn], lmin[maxn], rmax[maxn], rmin[maxn];
    
    inline int max(int a, int b) {
        return a > b ? a : b;
    }
    inline int min(int a, int b) {
        return a < b ? a : b;
    }
    void push_up(int rt) {
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
        smax[rt] = max(max(smax[rt << 1], smax[rt << 1 | 1]), rmax[rt << 1] + lmax[rt << 1 | 1]);
        smin[rt] = min(min(smin[rt << 1], smin[rt << 1 | 1]), rmin[rt << 1] + lmin[rt << 1 | 1]);
        lmax[rt] = max(lmax[rt << 1], sum[rt << 1] + lmax[rt << 1 | 1]);
        lmin[rt] = min(lmin[rt << 1], sum[rt << 1] + lmin[rt << 1 | 1]);
        rmax[rt] = max(rmax[rt << 1 | 1], sum[rt << 1 | 1] + rmax[rt << 1]);
        rmin[rt] = min(rmin[rt << 1 | 1], sum[rt << 1 | 1] + rmin[rt << 1]);
    }
    
    void update(int i, int x, int l, int r, int rt) {
        if (i == l && i == r) {
            sum[rt] = smax[rt] = smin[rt] = lmax[rt] = lmin[rt] = rmax[rt] = rmin[rt] = x;
            return;
        }
        int m = (l + r) >> 1;
        if (i <= m)
            update(i, x, lson);
        else
            update(i, x, rson);
        push_up(rt);
    }
    
    int main() {
        int n, i, x, j, m;
        scanf("%d", &n);
        for (i = 1; i <= n; ++i) {
            scanf("%d", &x);
            update(i, x, 1, n, 1);
        }
        scanf("%d", &m);
        for (i = 0; i < m; ++i) {
            scanf("%d%d", &j, &x);
            update(j, x, 1, n, 1);
            if (sum[1] == smax[1]) {
                printf("%d\n", sum[1] - smin[1]);
            } else {
                printf("%d\n", max(smax[1], sum[1] - smin[1]));
            }
        }
        return 0;
    }


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值