输入n, m,n表示n种操作,m表示最多可以容纳m个串。
第一种操作:先在容器里找是否存在这个串,如果不存在,则添加在末尾,这个串携带了一个值v。
如果存在,则先把之前存在的那个拿出来,然后在后面添加这个串,注意此时输入的这个v值不管用!!!!,v还是以前的那个v.
第二种操作:先在这个容器内是否存在这个串,如果存在则看v值,v值为-1, 0, 1,分别表示左边那个,自己,右边那个,如果存在则输出那个串携带的v值,不存在则输出invalid.
#include<bits/stdc++.h> using namespace std; const int M = 5e5 + 100; typedef pair<int, int> pii;
//flag表示v值,ind表示是第几个串,如果先出去了再进来算另外一个 int flag[M * 120], ind[M * 120]; int t, n, m, tot; char s[12]; int tree[M * 12][11];
//判断这个串是否出现过与是否已经出去了。下标对应cnt int vis[M];
//左边,右边。 int le[M], re[M];
//保存v值。下标对应cnt int ans[M];
容器头元素,尾元素。 int mi, ma; void add(char ch[], int in, int val) { int root = 0, len = strlen(ch); for(int i = 0; i < len; i++) { int id = ch[i] - '0'; if(!tree[root][id]) { memset(tree[tot], 0, sizeof(tree[tot])); ind[tot] = -1; flag[tot] = -1; tree[root][id] = tot++; } root = tree[root][id]; } ind[root] = in; flag[root] = val; } pii findx(char ch[]) { int root = 0, len = strlen(ch); for(int i = 0; i < len; i++) { int id = ch[i] - '0'; root = tree[root][id]; if(!root) return pii(-1, -1); } return pii(ind[root], flag[root]); } int main() { scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); tot = 1; memset(tree[0], 0, sizeof(tree[0])); int opt, v;
//给串标号,如果出去了再进来也要++. int cnt = 0;
//表示容器里有几个元素。 int num = 0; mi = 1, ma = -1; for(int i = 1; i <= n; i++) { scanf("%d%s%d", &opt, s, &v); int tmp = ma; if(opt == 0) { pii p = findx(s); if(p.first == -1 || vis[p.first] == 0) { cnt++; vis[cnt] = 1; le[cnt] = re[cnt] = -1; ans[cnt] = v; add(s, cnt, v); if(tmp != -1) re[tmp] = cnt; le[cnt] = tmp; ma = cnt; num++; printf("%d ", v); } else {
//更改的是第一个 if(p.first == mi) mi = re[mi]; if(num == 1) mi = p.first; printf("%d ", p.second);
//注意这个!!!!更之前tmp有关,可能更改的是最后一个 if(p.first == ma) continue;
//链表操作。 if(le[p.first] != -1) re[le[p.first] ] = re[p.first]; if(re[p.first] != -1) le[re[p.first] ] = le[p.first];
//!!!!因为ma可能更改了,所以之前要特判一下p.first == ma. if(tmp != -1) re[tmp] = p.first; le[p.first] = tmp; re[p.first] = -1; ma = p.first; } } else { pii p = findx(s); if(p.first != -1 && vis[p.first] == 1) { if(v == 0) printf("%d ", p.second); else if(v == -1) { if(le[p.first] != -1 && vis[p.first ] == 1) printf("%d ", ans[le[p.first] ]); else printf("Invalid "); } else { if(re[p.first] != -1 && vis[p.first ] == 1) printf("%d ", ans[re[p.first] ]); else printf("Invalid "); } } else printf("Invalid "); } if(num > m) { num--;
//表示出容器。 vis[mi] = 0; int tm = re[mi]; if(tm != -1) le[tm] = -1; re[mi] = -1; mi = tm; } } } return 0; } /* 1 8 3 0 0101010 1 0 0101011 2 1 0101010 1 0 1100000 3 0 0101011 -1 0 1111111 4 1 0101011 -1 1 0101010 0 */
并查集加速链表操作
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 100; unordered_map<int, int> fa; int findfa(int x) { if (!fa.count(x)) return x; return fa[x] = findfa(fa[x]); } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); int n, q; scanf("%d %d", &n, &q); int op, x; while (q--) { scanf("%d %d", &op, &x); if (op == 1) { fa[x] = findfa(x + 1); } else { int ans = findfa(x); if (ans > n) ans = -1; printf("%d ", ans); } } return 0; }