The 2025 Sichuan Provincial Collegiate Programming Contest

I. Essentially Different Suffixes

字符串hash或者tire树

#include<bits/stdc++.h>
using namespace std;

int tr[300010][30];int cnt[300010];
int idx=0;int ans=0;
string str;
void ins(string str){
    int p=0;
    for(auto c:str){
        if(!tr[p][c-'a'])tr[p][c-'a']=++idx;
        p=tr[p][c-'a'];
        if(cnt[p]==0){
            cnt[p]=1;ans++;
        }
    }

}
signed main(){
    std::ios::sync_with_stdio(false);
    int n;cin>>n;
    for(int i=1;i<=n;i++){
        cin>>str;
        reverse(str.begin(),str.end());
        ins(str);
       
    } 
    cout<<ans;
}

H. Hututu

xy独立
一般都可以小的一直+1-1等,大的走
如果差的是偶数可以这么做
如果差的是奇数,差1,小的最后一步走+2,等大的一步-1
如果小的没有最后一步,得特判,得加一步,成为差2
不是差1,最后一步走+2,等大的一步-1,之后一直+1-1即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long


signed main(){
    std::ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--){
       int sx,sy,ex,ey;cin>>sx>>sy>>ex>>ey;
      
       int t1=(abs(ex-sx)+1)/2;int t2=(abs(ey-sy)+1)/2;
        int dis=max(t1,t2);if(min(t1,t2)==0&&max(t1,t2)==1)dis++;
        cout<<dis<<'\n';
    }
}

F.Inversion Pairs

cf风格的前缀后缀题

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1000010;
int n;
int pre1[N];
int suf0[N];


signed main(){
    std::ios::sync_with_stdio(false);  

    int T;cin>>T;
    while(T--){
        cin>>n;
      string s;cin>>s;s="a"+s;
     
        pre1[0]=0;
        for(int i=1;i<=n;i++){
            int t=(s[i]!='0')?1:0;
            pre1[i]=pre1[i-1]+t;
        }
        suf0[n+1]=0;
        for(int i=n;i>=1;i--){
            int t=(s[i]!='1')?1:0;
            suf0[i]=suf0[i+1]+t;
        }

        int ans=0;int res=0;
        for(int i=n;i>=1;i--){
            if(s[i]=='1')ans+=suf0[i+1];
        }
        //全填0
        res=ans;
        for(int i=1;i<=n;i++){//这个是最后一个填1
            if(s[i]=='?'){
                res-=pre1[i-1];
                res+=suf0[i+1];
                ans=max(ans,res);
            }
        }
        
       cout<<ans<<'\n';
    }
}

J. Sichuan Provincial Contest

f[u][j]为u的子树中长度为j的前缀条数
g[u][j]为u的子树中长度为j的后缀条数
类似求直径的转移
统计答案时,如果是P,sccp和pc来自同一子树,需要减掉一些路径,是sccp作为前缀,pc作为后缀,每个sccp和自己配了一遍多出来一条路径

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1000010;
string a;int n;
int f[N][6];
int g[N][6];
vector<int> G[N];


void dfs(int u,int fa){

for(auto v:G[u]){
    if(v==fa)continue;
    dfs(v,u);
    if(a[u]=='S'){
    //f[u][1]++;
    g[u][5]+=g[v][4];
    }
    else if(a[u]=='C'){
        //作为2
        f[u][2]+=f[v][1];
        g[u][4]+=g[v][3];
        //作为3
        f[u][3]+=f[v][2];
        g[u][3]+=g[v][2];
        //作为5
        f[u][5]+=f[v][4];
        //g[u][1]++;
    }else if(a[u]=='P'){
        f[u][4]+=f[v][3];
        g[u][2]+=g[v][1];
    }
}

if(a[u]=='S')f[u][1]++;
if(a[u]=='C')g[u][1]++;


}

signed main(){
 std::ios::sync_with_stdio(false);
int T;cin>>T;
while(T--){
        cin>>n;for(int i=1;i<=n;i++){G[i].clear();
        for(int j=1;j<=5;j++)f[i][j]=g[i][j]=0;
        }
    cin>>a;a="a"+a;
    for(int i=1;i<=n-1;i++){
        int u,v;cin>>u>>v;
        G[u].push_back(v);G[v].push_back(u);
    }
dfs(1,-1);
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=5;j++){

            ans+=f[i][j]*g[i][5-j+1];  
        }
        if(a[i]=='P')ans-=f[i][4];
            
    }

    cout<<ans<<'\n';
}

}

A.Minimum Product

最小乘积模型板子
\(f[sum][i]\)表示乘积,走到i

#include<bits/stdc++.h>
using namespace std;
#define INF 1e17
#define int long long
const int N=310;
struct Node{
    int v,a,b;
};
vector<Node> G[N];int n,m;
int f[N*200][310];

signed main(){
    std::ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--){
        cin>>n>>m;
        for(int i=1;i<=n;i++)G[i].clear();
        for(int s=0;s<=n*200;s++)
        for(int i=1;i<=n;i++)f[s][i]=INF;
        while(m--){
            int u,v,a,b;
            cin>>u>>v>>a>>b;
            G[u].push_back({v,a,b});
        }

        
        f[0][1]=0;
        for(int s=0;s<=n*200;s++){
            for(int i=1;i<=n;i++){
                if(f[s][i]>INF/2)continue;
                for(auto [v,a,b]:G[i]){
                    f[s+a][v]=min(f[s+a][v],f[s][i]+b);
                }

            }
        }
        int ans1=INF;int ans2=1;
        for(int s=1;s<=n*200;s++){
            if(f[s][n]>INF/2)continue;
            if(ans1*ans2>s*f[s][n]){
                ans1=s;ans2=f[s][n];
            }
        }
        //cout<<f[0][1]<<" "<<f[2][4]<<" "<<f[7][5]<<'\n';
        cout<<ans1<<" "<<ans2<<'\n';
    }
}

C.Optimal 时间

神秘迭代,mark一下,以后遇到类似的看

posted @ 2025-08-26 20:54  arin876  阅读(63)  评论(0)    收藏  举报