Link:
C:
最好采取逆序贪心,否则要多考虑好几种情况
(从前往后贪心的话不能无脑选“dreamer”,"er"可能为"erase"/"eraser"的前缀)
#include <bits/stdc++.h> using namespace std; string s; int main() { cin>>s; for(int cur=s.size();cur;) if(cur>=5&&s.substr(cur-5,5)=="erase") cur-=5; else if(cur>=5&&s.substr(cur-5,5)=="dream") cur-=5; else if(cur>=6&&s.substr(cur-6,6)=="eraser") cur-=6; else if(cur>=7&&s.substr(cur-7,7)=="dreamer") cur-=7; else return puts("NO"),0; puts("YES"); return 0; }
注意:$strncpy$和$s.substr()$的第三个参数为长度
D:
题意:求与点$i$在图$G1$和图$G2$中的连通块序号均相同的点的个数
设1个点的序号对为$(a,b)$,其实就是求每对$(a,b)$的个数
然而我一开始沙茶得以为只能$O(n^2)$来统计……
明显用上$set$就只要$O(m*log(n))$了嘛,多维的统计都可以用$set$优化!
先跑两遍$dfs$求出每个点的$(a,b)$,再利用$set$优化$pair$的统计就好了
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> P; const int MAXN=2e5+10; map<P,int> mp; struct edge{int nxt,to;}e[MAXN<<2]; int c1[MAXN],c2[MAXN],sum1[MAXN],sum2[MAXN]; int n,k,l,x,y,head[MAXN],vis[MAXN],res[MAXN],tot,cnt; void add_edge(int from,int to) { e[++tot].nxt=head[from];e[tot].to=to;head[from]=tot; e[++tot].nxt=head[to];e[tot].to=from;head[to]=tot; } void dfs(int x,int c,int* col) { vis[x]=true;col[x]=c; for(int i=head[x];i;i=e[i].nxt) if(!vis[e[i].to]) dfs(e[i].to,c,col); } void solve(int esum,int* col) { tot=cnt=0; memset(head,0,sizeof(head)); memset(vis,false,sizeof(vis)); for(int i=1;i<=esum;i++) scanf("%d%d",&x,&y),add_edge(x,y); for(int i=1;i<=n;i++) if(!vis[i]) dfs(i,++cnt,col); } int main() { scanf("%d%d%d",&n,&k,&l); memset(res,0x3f,sizeof(res)); solve(k,c1);solve(l,c2); for(int i=1;i<=n;i++) sum1[c1[i]]++,sum2[c2[i]]++; for(int i=1;i<=n;i++) mp[P(c1[i],c2[i])]++; for(int i=1;i<=n;i++) printf("%d ",mp[P(c1[i],c2[i])]); return 0; }
如果只求连通块最好使用并查集
提升效率并能减少代码量