[Atcoder Regular Contest 065] Tutorial

Link:

ARC065 传送门

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;
}
Problem C

注意:$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;
}
Problem D

如果只求连通块最好使用并查集

提升效率并能减少代码量

E:

F:

猜你喜欢

转载自www.cnblogs.com/newera/p/9303207.html