传送门:点击打开链接
题意:有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; }