2022NOIPA层联测6
问题 A: 【2022NOIP联测6 10月10日】构造字符串(str)
仔细的对着题解找不同,还是感觉就是一模一样……suddenlly求mex清空vis数组忘了0从1开始清,So WA 30,我又2了……
然后发现错误以为可以AC结果WA 60,忽然发现:不相同的字符之间要连边,但是不只有0!!任意长度的最长公共前缀的末尾都一定不相等!!!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1003; int m, n, fa[maxn], val[maxn], tot; bool vis[maxn]; set<int> w[maxn]; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } struct node { int fr, to; }b[maxn]; void add(int x, int y) { b[++tot].fr = x; b[tot].to = y; } void add2(int x, int y) { w[x].insert(y); w[y].insert(x); } int find(int x) { if(x == fa[x]) return x; return fa[x] = find(fa[x]); } int main() { //freopen("str2.in", "r", stdin); n = read(); m = read(); for(int i=1; i<=n; i++) fa[i] = i; for(int i=1; i<=m; i++) { int x = read(), y = read(), z = read(); if(z) { for(int j=x,k=y; j<=x+z-1; j++,k++) { fa[find(j)] = fa[find(k)]; } add(x+z, y+z); } else add(x, y); } for(int i=1; i<=tot; i++) { //printf("find : %d %d\n", find(b[i].fr), find(b[i].to)); if(find(b[i].fr) == find(b[i].to)) { printf("-1"); exit(0); } else add2(find(b[i].fr), find(b[i].to)); } memset(val, -1, sizeof(val)); for(int i=1; i<=n; i++) { if(val[find(i)] != -1) continue; int mex = 0; for(int j=0; j<=n; j++) vis[j] = 0; for(int x : w[find(i)]) { //printf("val[%d] = %d\n", x, val[x]); //if(val[x] == mex) mex++; vis[val[x]] = 1; } while(vis[mex]) mex++; val[find(i)] = mex; //printf("val[%d] = %d\n", find(i), val[find(i)]); } for(int i=1; i<=n; i++) { printf("%d ", val[find(i)]); } return 0; }
问题 B: 【2022NOIP联测6 10月10日】寻宝(treasure)
依然希望求救。。
问题已经解决!!
引子是一段对话:
我:可以问T2吗?
Chen_jr:……
我:对呀对呀!
Chen_jr:你过样例了吗,大样例?
我:过了呢,我有70 pts
Chen_jr:那是你dfs写错了吧
……
于是我到牛棚回声里鹤到了他的dfs。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5e4 + 3; int n, m, sta[maxn], top, k, q, fa[maxn]; char c[maxn], s[maxn]; bool vis[maxn]; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } inline int id(int x, int y) { return (x-1)*m+y; } struct node { int next, to; }a[maxn<<1]; int head[maxn], len; void add(int x, int y) { a[++len].to = y; a[len].next = head[x]; head[x] = len; } int check(int x, int y) { if(x == y) return true; vis[x] = 1; sta[++top] = x; for(int i=head[x]; i; i=a[i].next) { int v = a[i].to; if(vis[v]) continue; if(v == y) return true; if(check(v, y)) return true; } return false; } queue<pair<int, int> > qu; void bfs(int x, int y) { qu.push(make_pair(x, y)); int tot = id(x, y); while(!qu.empty()) { int i = qu.front().first, j = qu.front().second; qu.pop(); if(i-1>=1 && s[id(i-1,j)] == '.' && fa[id(i-1,j)] == id(i-1,j)) { qu.push(make_pair(i-1, j)); fa[id(i-1,j)] = tot; } if(j-1>=1 && s[id(i,j-1)]== '.' && fa[id(i,j-1)] == id(i,j-1)) { qu.push(make_pair(i, j-1)); fa[id(i, j-1)] = tot; } if(i+1<=n && s[id(i+1,j)] == '.' && fa[id(i+1,j)] == id(i+1,j)) { qu.push(make_pair(i+1,j)); fa[id(i+1,j)] = tot; } if(j+1<=m && s[id(i,j+1)] == '.' && fa[id(i,j+1)] == id(i,j+1)) { qu.push(make_pair(i,j+1)); fa[id(i,j+1)] = tot; } } } int main() { n = read(); m = read(); k = read(); q = read(); for(int i=1; i<=n*m; i++) fa[i] = i; for(int i=1; i<=n; i++) { scanf("%s", c+1); for(int j=1; j<=m; j++) s[id(i,j)] = c[j]; } for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(s[id(i,j)] == '.' && fa[id(i,j)] == id(i,j)) { bfs(i, j); } } } for(int i=1; i<=k; i++) { int a1 = read(), b = read(), c = read(), d = read(); if(s[id(a1,b)] == '#' || s[id(c,d)] == '#' || fa[id(a1,b)] == fa[id(c,d)]) continue; add(fa[id(a1,b)], fa[id(c,d)]); } while(q--) { int a1 = read(), b = read(), c = read(), d = read(); printf("%d\n", check(fa[id(a1,b)], fa[id(c,d)])); while(top > 0) vis[sta[top--]] = false; } return 0; }
然而依然不知道我的dfs为什么WA 70,区别只是预处理了一下啊,除了dfs的部分其他的什么都没变:
感谢char_phi:问题就是,由于加边的顺序问题,dfs时用这个点A指向的点B把这个点更新了,后来B又指向了一个点C,然后用C更新了B,但是它本来也可以更新A却没有更新,导致每一个错误的点都是应该输出1的输出了0。改进方法就是把边先加上最后再dfs,其实和下面那种Floyed差不太多了。
char_phi太巨啦!!while(1) {char_phi csps rp++; char_ph noip rp++;} char_phi yyds,此处省略%*2^(1e9+7),mod*2^(1234567891)……
作为一个OIer的快乐,不仅在于学习奇妙的方法来解决奇妙的问题,还在于同学之间真挚纯洁的友谊,hzoi早已成为了我的第二个家……hz的每一个平凡的角落,构成了世界上最美丽的风景;hz的每一幕平凡的场景,构成了人世间最绚烂的画卷,我爱这里的日出日落,爱这里的流云晚霞,爱这里的每一株草每一朵花,爱这里带有梦想气味的风……如果可以不长大,我多么希望永远在这里当一名高中生……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 我感到很神奇,所以我看看这到底哪错了 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5e4 + 3; int n, m, sta[maxn], top, k, q, fa[maxn]; char c[maxn], s[maxn]; bool vis[maxn]; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } inline int id(int x, int y){return (x-1)*m+y;} struct node {int next, to;}a[maxn<<1]; int head[maxn], len; void add(int x, int y){ a[++len].to = y; a[len].next = head[x]; head[x] = len; } queue<pair<int, int> > qu; void bfs(int x, int y){ qu.push(make_pair(x, y)); int tot = id(x, y); while(!qu.empty()){ int i = qu.front().first, j = qu.front().second; qu.pop(); if(i-1>=1 && s[id(i-1,j)] == '.' && fa[id(i-1,j)] == id(i-1,j)) {qu.push(make_pair(i-1, j)); fa[id(i-1,j)] = tot;} if(j-1>=1 && s[id(i,j-1)] == '.' && fa[id(i,j-1)] == id(i,j-1)) {qu.push(make_pair(i, j-1)); fa[id(i, j-1)] = tot;} if(i+1<=n && s[id(i+1,j)] == '.' && fa[id(i+1,j)] == id(i+1,j)) {qu.push(make_pair(i+1,j)); fa[id(i+1,j)] = tot;} if(j+1<=m && s[id(i,j+1)] == '.' && fa[id(i,j+1)] == id(i,j+1)) {qu.push(make_pair(i,j+1)); fa[id(i,j+1)] = tot;} } } // set<int> hv[maxn]; void dfs(int x, int l){ vis[x] = 1; hv[l].insert(x); for(int i=head[x]; i; i=a[i].next){ int y = a[i].to; if(vis[y]) continue; dfs(y, l); } } // int check(int x, int y){ if(x == y) return true; if(hv[x].find(y) != hv[x].end()) return true; return false; } int aa[50005], bb[50005], cc[50005], dd[50005]; int main() { n = read(); m = read(); k = read(); q = read(); for(int i=1; i<=n*m; i++) fa[i] = i; for(int i=1; i<=n; i++){ scanf("%s", c+1); for(int j=1; j<=m; j++) s[id(i,j)] = c[j]; } for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) if(s[id(i,j)] == '.' && fa[id(i,j)] == id(i,j)) bfs(i, j); for(int i=1; i<=k; i++) { int a1 = read(), b = read(), c = read(), d = read(); aa[i] = a1, bb[i] = b, cc[i] = c, dd[i] = d; if(s[id(a1,b)] == '#' || s[id(c,d)] == '#' || fa[id(a1,b)] == fa[id(c,d)]) continue; // // memset(vis, 0, sizeof(vis)); // dfs(fa[id(c,d)], fa[id(a1,b)]); add(fa[id(a1,b)], fa[id(c,d)]); } for (int i = 1 ; i <= k ; ++ i){ memset(vis, 0, sizeof(vis)); dfs(fa[id(cc[i], dd[i])], fa[id(aa[i], bb[i])]); } while(q--) { int a1 = read(), b = read(), c = read(), d = read(); // printf("%d\n", check(fa[id(a1,b)], fa[id(c,d)])); } return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//对不同的地方有鲜明的 //标识 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5e4 + 3; int n, m, sta[maxn], top, k, q, fa[maxn]; char c[maxn], s[maxn]; bool vis[maxn]; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } inline int id(int x, int y) { return (x-1)*m+y; } struct node { int next, to; }a[maxn<<1]; int head[maxn], len; void add(int x, int y) { a[++len].to = y; a[len].next = head[x]; head[x] = len; } queue<pair<int, int> > qu; void bfs(int x, int y) { qu.push(make_pair(x, y)); int tot = id(x, y); while(!qu.empty()) { int i = qu.front().first, j = qu.front().second; qu.pop(); if(i-1>=1 && s[id(i-1,j)] == '.' && fa[id(i-1,j)] == id(i-1,j)) { qu.push(make_pair(i-1, j)); fa[id(i-1,j)] = tot; } if(j-1>=1 && s[id(i,j-1)]== '.' && fa[id(i,j-1)] == id(i,j-1)) { qu.push(make_pair(i, j-1)); fa[id(i, j-1)] = tot; } if(i+1<=n && s[id(i+1,j)] == '.' && fa[id(i+1,j)] == id(i+1,j)) { qu.push(make_pair(i+1,j)); fa[id(i+1,j)] = tot; } if(j+1<=m && s[id(i,j+1)] == '.' && fa[id(i,j+1)] == id(i,j+1)) { qu.push(make_pair(i,j+1)); fa[id(i,j+1)] = tot; } } } // set<int> hv[maxn]; void dfs(int x, int l) { vis[x] = 1; hv[l].insert(x); for(int i=head[x]; i; i=a[i].next) { int y = a[i].to; if(vis[y]) continue; dfs(y, l); } } // int check(int x, int y) { if(x == y) return true; if(hv[x].find(y) != hv[x].end()) return true; return false; } int main() { n = read(); m = read(); k = read(); q = read(); for(int i=1; i<=n*m; i++) fa[i] = i; for(int i=1; i<=n; i++) { scanf("%s", c+1); for(int j=1; j<=m; j++) s[id(i,j)] = c[j]; } for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(s[id(i,j)] == '.' && fa[id(i,j)] == id(i,j)) { bfs(i, j); } } } for(int i=1; i<=k; i++) { int a1 = read(), b = read(), c = read(), d = read(); if(s[id(a1,b)] == '#' || s[id(c,d)] == '#' || fa[id(a1,b)] == fa[id(c,d)]) continue; // memset(vis, 0, sizeof(vis)); dfs(fa[id(c,d)], fa[id(a1,b)]); add(fa[id(a1,b)], fa[id(c,d)]); } while(q--) { int a1 = read(), b = read(), c = read(), d = read(); // printf("%d\n", check(fa[id(a1,b)], fa[id(c,d)])); } return 0; }
and 一题多解之并查集:(比我的bfs好看得多)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5e4 + 3; int n, m, sta[maxn], top, k, q, fa[maxn]; char c[maxn], s[maxn]; bool vis[maxn]; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } inline int id(int x, int y) { return (x-1)*m+y; } int find(int x) { if(x == fa[x]) return x; return fa[x] = find(fa[x]); } inline void merge(int x, int y) { x = find(x), y = find(y); if(x == y) return; fa[y] = x; } struct node { int next, to; }a[maxn<<1]; int head[maxn], len; void add(int x, int y) { a[++len].to = y; a[len].next = head[x]; head[x] = len; } int check(int x, int y) { if(x == y) return true; vis[x] = 1; sta[++top] = x; for(int i=head[x]; i; i=a[i].next) { int v = a[i].to; if(vis[v]) continue; if(v == y) return true; if(check(v, y)) return true; } return false; } int main() { n = read(); m = read(); k = read(); q = read(); for(int i=1; i<=n*m; i++) fa[i] = i; for(int i=1; i<=n; i++) { scanf("%s", c+1); for(int j=1; j<=m; j++) s[id(i,j)] = c[j]; if(i != 1) { for(int j=1; j<=m; j++) { if(c[j] == '.' && s[id(i-1,j)] == '.') merge(id(i,j), id(i-1,j)); } } for(int j=2; j<=m; j++) { if(c[j] == '.' && c[j-1] == '.') merge(id(i,j-1), id(i,j)); } } for(int i=1; i<=k; i++) { int a1 = read(), b = read(), c = read(), d = read(); if(s[id(a1,b)] == '#' || s[id(c,d)] == '#' || find(id(a1,b)) == find(id(c,d))) continue; add(find(id(a1,b)), find(id(c,d))); } while(q--) { int a1 = read(), b = read(), c = read(), d = read(); printf("%d\n", check(find(id(a1,b)), find(id(c,d)))); while(top > 0) vis[sta[top--]] = false; } return 0; }
and一题多解之Floyed:(众所周知Floyed可以处理连通性,k最多只有100,老套路就是把它两边的点拿出来,然后就可以跑Floyed了)(能把一个套路用到每一个扯上关系的题里,所有变式应用自如,我不得不%%%)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; #define chu printf #define _f(i,a,b) for(register int i=(a);i<=(b);++i) #define f_(i,a,b) for(register int i=(a);i>=(b);--i) #define inf 2147483647 #define ll long long #define rint register int #define ull unsigned long long inline ll re() { ll x=0,h=1;char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')h=-1; ch=getchar(); } while(ch<='9'&&ch>='0') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*h; } const int N=-1; vector<bool>s[50000+10];//存矩阵(没告诉我具体) #=0;. =1 vector<int>id[50000+10];//方便维护节点编号 bool g[210][210],tag[50000+10]; int n,m,k,q,tot,code,belong[50000+10],belong2[50000+10],Code; int fa[50000+100];//dx[5]={0,1,0,-1},dy[5]={1,0,-1,0}; char ss[50000+10]; struct Qy { int x1,y1,x2,y2; }que[100000+100]; inline bool Safe(int x,int y) { if(x<=n&&x>=1&&y<=m&&y>=1)return 1; return 0; } inline int Father(int x) { return (fa[x]==x)?x:(fa[x]=Father(fa[x])); } inline void Merge(int x,int y) { //chu("merge:%d %d\n",x,y); int fx=Father(x),fy=Father(y); fa[fx]=fy; } int main() { // freopen("treasure4.in","r",stdin); // freopen("1.out","w",stdout); n=re(),m=re(),k=re(),q=re(); _f(i,1,n*m)fa[i]=i; _f(i,1,n) { scanf("%s",ss+1); id[i].push_back(0); s[i].push_back(0); _f(j,1,m) { if(ss[j]=='#') { //chu("%d %d is not can\n",i,j); s[i].push_back(0); id[i].push_back(0); } else { // chu("%d %d is can\n",i,j); s[i].push_back(1); ++tot; id[i].push_back(tot); } } } // chu("tot:%d\n",tot); // _f(i,1,n) // { // _f(j,1,m)if(s[i][j])chu("1");else chu("0"); // chu("\n"); // } _f(i,1,n) _f(j,1,m) { if(s[i][j]==0)continue; if(Safe(i,j+1)&&s[i][j+1]==1)Merge(id[i][j],id[i][j+1]); if(Safe(i+1,j)&&s[i+1][j]==1)Merge(id[i][j],id[i+1][j]); } //给每个联通块编号,belong[x]=code, _f(i,1,tot) if(fa[i]==i)belong[i]=++code; // chu("code:%d\n",code); _f(i,1,tot)belong[i]=belong[Father(i)]; _f(i,1,k)//非常少,直接把涉及到的拿出来呗 { int x1=re(),y1=re(),x2=re(),y2=re(); que[i]={x1,y1,x2,y2}; if(!tag[belong[id[x1][y1]]]) { // deq[++deqcnt]=belong[id[x1][y1]]; belong2[belong[id[x1][y1]]]=++Code; tag[belong[id[x1][y1]]]=1; } if(!tag[belong[id[x2][y2]]]) { // deq[++deqcnt]=belong[id[x2][y2]]; belong2[belong[id[x2][y2]]]=++Code; tag[belong[id[x2][y2]]]=1; } // g[belong[id[x1][y1]]][belong[id[x2][y2]]]=1; } _f(i,1,k) { int x1=que[i].x1,y1=que[i].y1,x2=que[i].x2,y2=que[i].y2; int cd1=belong[id[x1][y1]],cd2=belong[id[x2][y2]]; cd1=belong2[cd1],cd2=belong2[cd2]; g[cd1][cd2]=1; } _f(k,1,Code)g[k][k]=1; _f(ker,1,Code) _f(i,1,Code) _f(j,1,Code) g[i][j]=g[i][j]|(g[i][ker]&&g[ker][j]); _f(i,1,q) { int x1=re(),y1=re(),x2=re(),y2=re(); int fx=Father(id[x1][y1]),fy=Father(id[x2][y2]); if(fx==fy) { chu("1\n"); } else { int cd1=belong[id[x1][y1]],cd2=belong[id[x2][y2]]; if(!belong2[cd1]||!belong2[cd2])//有的没归纳 { chu("0\n"); } else { cd1=belong2[cd1],cd2=belong2[cd2]; if(g[cd1][cd2])chu("1\n"); else chu("0\n"); } } } return 0; }
问题 C: 【2022NOIP联测6 10月10日】序列(seq)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e6 + 3; const ll inf = 1e17; int n, m; ll a[maxn], b[maxn], ans, fa[maxn], fb[maxn]; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } int main() { n = read(); m = read(); for(int i=1; i<=n; i++) { a[i] = read(); b[i] = read(); fa[i] = fa[i-1] + a[i]; fb[i] = fb[i-1] + b[i]; } while(m--) { int pos = read(); ll k = read(); int p = 0, p1 = pos; for(int i=1; i<pos; i++) { if(fb[p]*k-fa[p] < fb[i]*k-fa[i]) p = i; } for(int i=pos; i<=n; i++) { if(fa[p1]-fb[p1]*k < fa[i]-fb[i]*k) p1 = i; } ans = fa[p1]-fa[p]+fb[p]*k-fb[p1]*k; printf("%lld\n", ans); } return 0; }
问题 D: 【2022NOIP联测6 10月10日】构树(tree)
并不了解prufer序列的我以最暴力的方式生成了一棵树:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 12; const ll inf = 1e17; int n, m, ext[maxn], cnt, num, ans[maxn], las[maxn], fa[maxn]; ll tot; bool vis[maxn]; map<pair<int, int>, int> mp; map<ll, ll> mp2; inline int read() { int x = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') { f = -1; } ch = getchar(); } while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch^48); ch = getchar(); } return x * f; } void dfs(int a, int m) { if(a > m) { ll pat = 0; for(int i=2; i<=n; i++) { pat = (pat<<1)+(pat<<3)+fa[i]; } if(mp2.count(pat)) return; ans[num]++; mp2[pat] = ++tot; return; } int sz = cnt; for(int i=1; i<=sz; i++) { for(int j=las[i]+1; j<=n; j++) { if(vis[j]) continue; vis[j] = 1; ext[++cnt] = j; las[cnt] = 1; fa[j] = ext[i]; if(mp.count(minmax(ext[i], j))) num++; int fl = las[i]; las[i] = j; dfs(a+1, m); vis[j] = 0; cnt--; if(mp.count(minmax(ext[i], j))) num--; las[i] = fl; } } } int main() { n = read(); for(int i=1; i<n; i++) { int x = read(), y = read(); mp[minmax(x, y)] = i; } vis[1] = 1; ext[++cnt] = 1; las[cnt] = 1; dfs(1, n-1); for(int i=0; i<n; i++) { printf("%d ", ans[i]); } return 0; }