双向链表 csu1692 Vector Field

传送门:点击打开链接

题意:有n(<=3000)个位置,位置上有一个加速器,并且表示了方向,当例子通过这个加速器后,运动方向会变成加速器指向的方向,并且速度+1,加速器消失。

问最大能加速多少。

思路:最好的方法就是先离散化一下,然后用双向链表来维护,复杂度能降低到O(n^2)

不过当时太懒了,写了个set,双向链表的写法有空再补,先挖个坑

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<bitset>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck(x) cout<<"["<<x<<"]"
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
 
const int MX = 3e3 + 5;
struct Point {
    int x, y, d; //下左上右
} P[MX];
struct Data {
    int val, id;
    Data() {}
    Data(int _id, int _val) {
        val = _val; id = _id;
    }
    bool operator<(const Data &P) const {
        return val < P.val;
    }
};
 
set<Data>X[MX], Y[MX];
int tmpX[MX], tmpY[MX];
 
int solve(int u) {
    int begin = u;
    set<Data>::iterator it;
    int ret = 0;
    while(true) {
        ret++;
        X[P[u].x].erase(Data(u, P[u].y));
        Y[P[u].y].erase(Data(u, P[u].x));
        if(P[u].d == 0) {
            it = X[P[u].x].lower_bound(Data(0, P[u].y));
            if(it == X[P[u].x].begin()) return ret;
            it--;
        }
        if(P[u].d == 1) {
            it = Y[P[u].y].lower_bound(Data(0, P[u].x));
            if(it == Y[P[u].y].begin()) return ret;
            it--;
        }
        if(P[u].d == 2) {
            it = X[P[u].x].upper_bound(Data(0, P[u].y));
            if(it == X[P[u].x].end()) return ret;
        }
        if(P[u].d == 3) {
            it = Y[P[u].y].upper_bound(Data(0, P[u].x));
            if(it == Y[P[u].y].end()) return ret;
        }
        //if(begin==5&&P[u].x==2&&P[u].y==1) fuck(P[u].d);
        u = it->id;
    }
    return ret;
}
 
int main() {
    int n; //FIN;
    while(~scanf("%d", &n)) {
        for(int i = 1; i <= n; i++) {
            char w[10];
            scanf("%d%d%s", &P[i].x, &P[i].y, w);
            tmpX[i] = P[i].x; tmpY[i] = P[i].y;
            if(w[0] == 'v') P[i].d = 2;
            if(w[0] == '<') P[i].d = 1;
            if(w[0] == '^') P[i].d = 0;
            if(w[0] == '>') P[i].d = 3;
        }
        int sz1, sz2;
        sort(tmpX + 1, tmpX + 1 + n);
        sort(tmpY + 1, tmpY + 1 + n);
        sz1 = unique(tmpX + 1, tmpX + 1 + n) - tmpX - 1;
        sz2 = unique(tmpY + 1, tmpY + 1 + n) - tmpY - 1;
 
        for(int i = 1; i <= n; i++) {
            P[i].x = lower_bound(tmpX + 1, tmpX + 1 + sz1, P[i].x) - tmpX;
            P[i].y = lower_bound(tmpY + 1, tmpY + 1 + sz2, P[i].y) - tmpY;
        }
 
        int ans = 0;
        for(int u = 1; u <= n; u++) {
            for(int i = 1; i <= sz1; i++) X[i].clear();
            for(int i = 1; i <= sz2; i++) Y[i].clear();
            for(int i = 1; i <= n; i++) {
                X[P[i].x].insert(Data(i, P[i].y));
                Y[P[i].y].insert(Data(i, P[i].x));
            }
            int t = solve(u);
            ans = max(ans, t);
        }
        printf("%d\n", ans);
    }
    return 0;
}


补充:双向链表写法。果然链表比set不止快一点

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<bitset>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck(x) cout<<"["<<x<<"]"
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
 
const int MX = 3e3 + 5;
struct Point {
    int x, y, id;
    char d[2];
} P[MX];
 
struct List {
    int sz, A[MX], WHO[MX];
    int L[MX], R[MX], U[MX], D[MX];
    int New(int x) {
        A[x] = ++sz; WHO[sz] = x;
        L[sz] = R[sz] = U[sz] = D[sz] = 0;
        return sz;
    }
    void Delete(int rt) {
        R[L[rt]] = R[rt];
        L[R[rt]] = L[rt];
        D[U[rt]] = D[rt];
        U[D[rt]] = U[rt];
    }
    void Link_x(int u, int v) {
        R[u] = v; L[v] = u;
    }
    void Link_y(int u, int v) {
        D[u] = v; U[v] = u;
    }
} list1, list2;
 
bool cmp_x(Point a, Point b) {
    if(a.x == b.x) return a.y < b.y;
    return a.x < b.x;
}
bool cmp_y(Point a, Point b) {
    if(a.y == b.y) return a.x < b.x;
    return a.y < b.y;
}
bool cmp_id(Point a, Point b) {
    return a.id < b.id;
}
 
int solve(int u) {
    list2 = list1;
    int rt = list2.A[u], ret = 0;
    while(true) {
        ret++;
        list2.Delete(rt);
        if(P[u].d[0] == '^') rt = list2.U[rt];
        if(P[u].d[0] == '>') rt = list2.R[rt];
        if(P[u].d[0] == 'v') rt = list2.D[rt];
        if(P[u].d[0] == '<') rt = list2.L[rt];
        if(rt == 0) return ret;
        u = list2.WHO[rt];
    }
}
 
int main() {
    int n; //FIN;
    while(~scanf("%d", &n)) {
        list1.sz = 0;
        for(int i = 1; i <= n; i++) {
            P[i].id = i;
            scanf("%d%d%s", &P[i].x, &P[i].y, P[i].d);
            list1.New(i);
        }
 
        sort(P + 1, P + 1 + n, cmp_x);
        for(int l = 1, r; l <= n; l = r + 1) {
            for(r = l; r < n && P[l].x == P[r + 1].x; r++);
            for(int j = l + 1; j <= r; j++) {
                list1.Link_y(list1.A[P[j - 1].id], list1.A[P[j].id]);
            }
        }
        sort(P + 1, P + 1 + n, cmp_y);
        for(int l = 1, r; l <= n; l = r + 1) {
            for(r = l; r < n && P[l].y == P[r + 1].y; r++);
            for(int j = l + 1; j <= r; j++) {
                list1.Link_x(list1.A[P[j - 1].id], list1.A[P[j].id]);
            }
        }
        sort(P + 1, P + 1 + n, cmp_id);
 
        int ans = 0, t;
        for(int i = 1; i <= n; i++) {
            t = solve(i);
            ans = max(ans, t);
        }
        printf("%d\n", ans);
    }
    return 0;
}


你可能感兴趣的:(双向链表 csu1692 Vector Field)