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一下,以后遇到类似的看

浙公网安备 33010602011771号