ABC328

A

B

用set模拟即可

int cal(int x,int y){
    set<int>st;
    set<int>st2;
    while(x){
        st.insert(x%10);x/=10;
    }
    while(y){
        st2.insert(y%10);y/=10;
    }
    if(st==st2&&st.size()==1)return 1;
    return 0;
}
void solve(){
    int n;cin>>n;
    int cnt=0;
    rep(i,1,n){
        int x;cin>>x;
        rep(j,1,x){
            if(cal(i,j))cnt++;
        }
    }
    cout<<cnt<<endl;
}

C

题意:给定一个字符串,当s[i]=s[i-1]说这个字符是满足条件的,给定q次询问和[l,r],问区间内有多少个满足条件的字符
思路:
把满足条件的字符进行前缀和处理即可,注意答案变为了pre[r]-pre[l]

D

题意:
给定一个由A,B,C组成的字符串,遇到ABC子串就删除,同时把子串两边的子串连接起来,直到字符串中没有ABC为止
思路:
直接暴力可能会超时
不妨把字符串看成一个字符栈,每当该字符串的后缀3个字符为ABC时就删除

void solve(){
    string s;cin>>s;
    int n=s.size();s=" "+s;
    int ok=1;
    stack<char>stk;
    string t;t=" "+t;
    rep(i,1,n){
        t+=s[i];
        if(t.size()>=4){
            if(t.substr(t.size()-3,3)=="ABC"){
                t.erase(t.size()-3,3);
                // t.pop_back();
                // t.pop_back();
                // t.pop_back();
            }
        }
    }
    rep(i,1,t.size()-1){
        cout<<t[i];
    }
}

E

题意:给定一个图,求模K意义下的最小生成树边权之和
思路:
显然不能直接用kruskal之类的算法求解
N<=8,M<=28,所以考虑暴力枚举边的子集(2e8)
取出其中的n-1个,再利用并查集判断连通性,答案取min即可

int n,m,k;
int f[15];
int find(int x){
    if(f[x]!=x){
        f[x]=find(f[x]);
    }return f[x];
}
void merge(int x,int y){
    if(find(x)!=find(y)){
        f[find(x)]=find(y);
    }
}
void build(){
    rep(i,1,n)f[i]=i;
}
int ans=llmax;
void solve(){
    cin>>n>>m>>k;
    vector<pair<pii,int>>e;
    rep(i,1,m){
        int u,v,w;cin>>u>>v>>w;
        e.pb({{u,v},w});
    }
    for(int i=0;i<(1ll<<m);i++){
        if(__builtin_popcount(i)!=(n-1))continue;
        int sum=0;
        build();
        for(int j=0;j<m;j++){
            if(i&(1ll<<j)){
                int u=e[j].fi.fi,v=e[j].fi.se,w=e[j].se;
                merge(u,v);
                sum+=w;
            }
        }
        int fa=find(1);
        int ok=1;
        rep(i,1,n){
            if(find(i)!=fa)ok=0;
        }
        if(ok)ans=min(ans,sum%k);
    }
    cout<<ans<<endl;
}

F

题意:给定一系列三元组(a,b,c),从左往右遍历能构造出X满足X[a[i]]-X[b[i]]=c
思路:
带权并查集
让边权表示相对大小关系,即如果dis[x]=dis[y]+c,(dis数组为节点到该连通块根节点的距离),表示x比y大c
不在同一个连通块的节点没有相互大小关系
所以merge的时候判断,如果两个节点在同一个连通块,判断dis[x]是否等于dis[y]+c即可
如果两个节点不在同一个连通块,则需要连接两个节点的根节点(将其中一个根节点与另一个根节点进行连接,并将大小关系设置好)

int f[maxn];
int val[maxn];
int find(int x){
    if(f[x]!=x){
    int p=f[x];
    f[x]=find(f[x]);
    val[x]+=val[p];
    }
    return f[x];
}
int merge(int x,int y,int c){
    if(find(x)!=find(y)){
        int fx=find(x);
        int fy=find(y);
        f[fx]=fy;
        val[fx]+=c+val[y]-val[x];
        return 1;
    }else{
        if(val[x]-val[y]!=c)return 0;
        return 1;
    }
}
void solve(){
    int n,q;cin>>n>>q;
    rep(i,1,n)f[i]=i;
    rep(i,1,q){
        int u,v,w;cin>>u>>v>>w;
        if(merge(u,v,w))cout<<i<<' ';
    }
    cout<<endl;
}
posted @ 2025-06-10 19:00  Marinaco  阅读(21)  评论(0)    收藏  举报
//雪花飘落效果