zoukankan      html  css  js  c++  java
  • 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
    ",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
    ");
    		else printf("aoligei
    ");
    	}
    }
    

    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
    ",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
    ",Ans-1);
    }
    
  • 相关阅读:
    函数式宏定义与普通函数
    linux之sort用法
    HDU 4390 Number Sequence 容斥原理
    HDU 4407 Sum 容斥原理
    HDU 4059 The Boss on Mars 容斥原理
    UVA12653 Buses
    UVA 12651 Triangles
    UVA 10892
    HDU 4292 Food
    HDU 4288 Coder
  • 原文地址:https://www.cnblogs.com/-aether/p/12362051.html
Copyright © 2011-2022 走看看