2025 National Invitational of CCPC (Zhengzhou), 2025 CCPC Henan Provincial Collegiate Programming Contest

D.2025

M.川陀航空学院

J.Ring Trick

H.树论函数

结论题,所有点连通

G.直径与最大独立集

F.幻形之路

起点能到达的点b设为1,终点能到达的点b设为2
现在整个图最多有三块,按顺序一块1一块0一块2,走的时候分别判断

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


const int N=1010;
int n,m;int dx[4]={1,0,-1,0};int dy[4]={0,1,0,-1};
char a[N][N];
int b[N][N];
int d[N][N];
/*
10
5 5
.....
.....
.....
.....
.....
4 7
..#####
#######
..###..
.......
3 7
.######
#######
######.
*/

signed main(){
    std::ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            string str;cin>>str;
            for(int j=1;j<=m;j++){
                a[i][j]=str[j-1];
            }
        }
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){b[i][j]=0;}
        queue<pair<int,int>> q;q.push({1,1});b[1][1]=1;
        while(!q.empty()){
            auto [x,y]=q.front();q.pop();
            for(int k=0;k<4;k++){
                int tx=x+dx[k];int ty=y+dy[k];
                if(tx<=0||tx>=n+1||ty<=0||ty>=m+1)continue;
                if(a[tx][ty]=='#')continue;if(b[tx][ty]==1)continue;
                b[tx][ty]=1;q.push({tx,ty});
            }
        }
        q.push({n,m});b[n][m]=2;
        while(!q.empty()){
            auto [x,y]=q.front();q.pop();
            for(int k=0;k<4;k++){
                int tx=x+dx[k];int ty=y+dy[k];
                if(tx<=0||tx>=n+1||ty<=0||ty>=m+1)continue;
                if(a[tx][ty]=='#')continue;if(b[tx][ty]==2)continue;
                b[tx][ty]=2;q.push({tx,ty});
            }
        }

        deque<pair<int,int>> dq;
        int ans=0x3f3f3f3f;
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)d[i][j]=-1;
        dq.push_front({1,1});d[1][1]=0;
        while(!dq.empty()){
            auto [x,y]=dq.front();dq.pop_front();
          //  cout<<x<<" "<<y<<'\n';
            for(int k=0;k<4;k++){
                int tx=x+dx[k];int ty=y+dy[k];
                if(tx<=0||tx>=n+1||ty<=0||ty>=m+1)continue;
                if(d[tx][ty]!=-1)continue;
                if(b[tx][ty]==1)d[tx][ty]=d[x][y];
                else if(b[tx][ty]==0)d[tx][ty]=d[x][y]+1;
                else if(b[tx][ty]==2){d[tx][ty]=d[x][y];
                    ans=min(ans,d[x][y]);
                }
            if(d[tx][ty]==d[x][y])
                dq.push_front({tx,ty});
                else dq.push_back({tx,ty});
            }
        }
       
        cout<<ans<<'\n';

    }
}

E.双生魔咒

经典结论:前缀相同的字符串在字符串中连续排列,dfn连续
某个前缀出现cnt[p]次,由基本不等式,可以去到的最大价值是(cnt[p]/2)*(cnt[p]+1)/2
可以dfn奇数作为"引",偶数作为"根",就可以达到这个最大价值

#include<iostream>
using namespace std;
#define int long long
const int N=200010;
int tr[N][30];
int cnt[N];int idx=0;
void insertt(string str){
int p=0;
    for(auto c:str){
        if(!tr[p][c-'a'])tr[p][c-'a']=++idx;
        p=tr[p][c-'a'];
        cnt[p]++;
    }
}

int main(){
std::ios::sync_with_stdio(false);
int T;T=1;
while(T--){


    int n;cin>>n;
    for(int i=1;i<=2*n;i++){
    string str;cin>>str;insertt(str);
    }
    

    int ans=0;
    for(int i=1;i<=idx;i++){
        ans+=(cnt[i]/2)*((cnt[i]+1)/2);
    }
    cout<<ans<<'\n';
}
}
posted @ 2025-08-23 15:46  arin876  阅读(51)  评论(0)    收藏  举报