2020 CCPC-Wannafly Winter Camp Day3 解题报告

A


暴力就完事了


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}

const int N=1007;

ll a[N][N];
ll Ans[N];

int main(){
    int n=input();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            a[i][j]=input();

    if(n==2){
        printf("%lld %lld\n",a[1][2]/2,a[1][2]-a[1][2]/2);
        exit(0);
    }
    for(int i=2;i<=n-1;i++){
        Ans[i]=(a[i-1][i]+a[i][i+1]-a[i-1][i+1])/2;
    }
    Ans[1]=a[1][2]-Ans[2];
    Ans[n]=a[n-1][n]-Ans[n-1];
    for(int i=1;i<=n;i++){
        printf("%lld ",Ans[i]);
    }
}

E


每次对答案产生贡献只有最右下角的棋子才会对答案产生贡献(类似博弈论的推理),那么只要统计当前位置被翻转了多少次,边维护前缀和边算答案就行了。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}

const int N=507;

int n,m;
char s[507];
int a[N][N];
int d[N][N];

int main(){
    int T=input();
    while(T--){
        n=input(),m=input();
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            for(int j=1;j<=m;j++){
                a[i][j]=s[j]=='0'? 0:1;
            }
        }

        for(int i=1;i<=n+5;i++)
            for(int j=1;j<=m+5;j++)
                d[i][j]=0;

        int cnt=0;
        for(int i=n;i>=1;i--){
            for(int j=m;j>=1;j--){
                d[i][j]+=d[i+1][j]+d[i][j+1]-d[i+1][j+1];
                if((d[i][j]+a[i][j])%2==1)
                    d[i][j]++,cnt++;
            }
        }


        if(cnt%2) printf("call\n");
        else printf("aoligei\n");
    }
}

G


答案显然是:到所有标记点的距离*2-到最远的点的距离。树dp维护这个式子,就可以做出来了。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}

#define PII pair<int,ll>
#define fr first
#define sc second
#define mp make_pair
#define pb push_back

const int N=5e5+7;

ll dis1[N],dis2[N],sum[N],siz[N];
vector<PII> G[N];
int n,k;

void Ins(int u,int v,ll w){
    G[u].pb(mp(v,w));
    G[v].pb(mp(u,w));
}

void modify(int dis,int u){
    if(dis>dis1[u]) dis2[u]=dis1[u],dis1[u]=dis;
    else if(dis>dis2[u]) dis2[u]=dis;
}

void dfs1(int u,int fa){
    for(auto vv:G[u]){
        ll v=vv.fr,w=vv.sc;
        if(v==fa) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]){
            sum[u]+=2*w+sum[v];
            modify(dis1[v]+w,u);
        }
    }
}

void dfs2(int u,int fa){
    for(auto vv:G[u]){
        ll v=vv.fr,w=vv.sc;
        if(v==fa) continue;
        sum[v]=sum[u]-2*w*(siz[v]==k)+2*w*(siz[v]==0);
        if(dis1[u]==dis1[v]+w){
            if(siz[u]-siz[v]!=0){
                modify(dis2[u]+w,v);
            }
        }else modify(dis1[u]+w,v);
        dfs2(v,u);
    }
}

int main(){
    n=input(),k=input();
    for(int i=1;i<n;i++){
        int u=input(),v=input(),w=input();
        Ins(u,v,w);
    }

    for(int i=1;i<=k;i++){
        int x=input();
        siz[x]=1;
    }

    dfs1(1,0),dfs2(1,0);

    for(int i=1;i<=n;i++){
        printf("%lld\n",sum[i]-dis1[i]);
    }
}

C


转换为染色问题,相当于求给图中每一个点染色,有边相连的点颜色不能相同,最少需要多少种颜色,而最多的路径便是颜色的数量-1。


#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll input(){
    ll x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return f? -x:x;
}

const int N=20;

int G[N][N],color[N];
int Ans=0x3f3f3f3f;
int cnt=0;
int n,m;

bool check(int u,int c){
    for(int i=1;i<=n;i++){
        if(G[u][i]&&color[i]==c){
            return 0;
        }
    }
    return 1;
}

void dfs(int dep){
    if(cnt>=Ans) return;
    if(dep>n){Ans=min(cnt,Ans);return;}
    for(int i=1;i<=cnt+1;i++){
        if(check(dep,i)){
            color[dep]=i;
            if(i>cnt){
                cnt++;
                dfs(dep+1);
                cnt--;
            }else dfs(dep+1);
            color[dep]=0;
        }
    }
}

int main(){
    n=input(),m=input();
    for(int i=1;i<=m;i++){
        int u=input(),v=input();
        G[u][v]=G[v][u]=1;
    }
    dfs(1);
    printf("%d\n",Ans-1);
}

猜你喜欢

转载自www.cnblogs.com/-aether/p/12362051.html
今日推荐