1. 程式人生 > >20180723 考試記錄

20180723 考試記錄

set swa 進行 dfs bubuko int sum long long out

T1 Matrix

技術分享圖片

Solution

列完式子後發現可以用前綴和進行優化為O(nm)

總結

矩陣題看見矩乘超時就列式子嘗試簡化

Code

//By Menteur_Hxy
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
typedef long long LL;

int read() {
    int x=0,f=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}

const int N=2010;
int n,m;
LL ans;
LL A[N][N],B[N][N],t1[N][N],t2[N][N];

int main() {
    freopen("matrix.in","r",stdin);
    freopen("matrix.out","w",stdout);
    n=read();m=read();
    F(i,1,n) F(j,1,n) A[i][j]=read();
    F(i,1,n) F(j,1,n) B[i][j]=read();
    F(i,1,n) F(j,1,n) t1[i][j]=t1[i-1][j]+A[i][j];
    F(i,1,n) F(j,1,n) t2[i][j]=t2[i][j-1]+B[i][j];
    while(m--) {
        int a=read(),b=read(),c=read(),d=read();
        if(a>c) swap(a,c); if(b>d) swap(b,d);
        ans=0;
        F(i,1,n) ans+=(t1[c][i]-t1[a-1][i])*(t2[i][d]-t2[i][b-1]);
        printf("%lld\n",ans);
    }
    return 0;
}

T2 Tower

技術分享圖片

Soulution

反(hen)證(xian)法(ran)可知距離最小的點的x坐標與y坐標一定是給出點坐標中\(n^2\)枚舉x和y即可

Code

//By Menteur_Hxy
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define M(a,b) memset(a,(b),sizeof(a))
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
typedef long long LL;

int read() {
    int x=0,f=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-')f=-f; c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}

const int N=60;
int n;
LL xi[N],yi[N],mi[N],dis[N];

int main() {
    freopen("tower.in","r",stdin);
    freopen("tower.out","w",stdout);
    n=read();
    F(i,1,n) xi[i]=read(),yi[i]=read();
    M(mi,0x3f);
    F(i,1,n) F(j,1,n) {
        int x=xi[i],y=yi[j];
        F(k,1,n) dis[k]=abs(x-xi[k])+abs(y-yi[k]);
        sort(dis+1,dis+1+n);
        LL sum=0;
        F(k,1,n) sum+=dis[k],mi[k]=min(mi[k],sum);
    }
    F(i,1,n) printf("%lld\n",mi[i]);
    return 0;
} 

T3 Tree

技術分享圖片

Solution

很簡單的樹形dp就能做出來。。

Code

無高精版:

//By Menteur_Hxy
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
#define E(i,u) for(register int i=head[u];i;i=nxt[i])
using namespace std;
typedef long long LL;

int read() {
    int x=0,f=1; char c=getchar();
    while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
    while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    return x*f;
}

const int N=1010;
int n,cnt,rt;
int nxt[N],to[N],head[N],deg[N],du[N];
LL dp[N][2],g[N][2];

void dfs(int u) {
    LL sum=0,mul=1;
    E(i,u) { int v=to[i];
        dfs(v); 
        sum+=max(dp[v][0],dp[v][1]);
        if(dp[v][0]>dp[v][1]) mul*=g[v][0];
        else if(dp[v][0]<dp[v][1]) mul*=g[v][1];
        else mul*=(g[v][0]+g[v][1]);
    }
    dp[u][0]=sum,g[u][0]=mul;
    E(i,u) { int v=to[i];
        LL now=sum-max(dp[v][0],dp[v][1])+dp[v][0]+1;
        if(now>dp[u][1]) {
            dp[u][1]=now;
            if(dp[v][0]>dp[v][1]) g[u][1]=mul;
            else if(dp[v][0]<dp[v][1]) g[u][1]=mul/g[v][1]*g[v][0];
            else g[u][1]=mul/(g[v][0]+g[v][1])*g[v][0];
        } else if(now==dp[u][1]) {
            if(dp[v][0]>dp[v][1]) g[u][1]+=mul;
            else if(dp[v][0]<dp[v][1]) g[u][1]+=mul/g[v][1]*g[v][0];
            else g[u][1]+=mul/(g[v][0]+g[v][1])*g[v][0];
        }   
    }   
}

#define add(a,b) nxt[++cnt]=head[a],to[cnt]=b,head[a]=cnt
int main() {
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    n=read();
    F(i,1,n) {
        int u=read(); deg[u]=read();
        F(j,1,deg[u]) {
            int v=read();
            add(u,v);du[v]++;
        }
    }
    F(i,1,n) if(!du[i]) {rt=i;break;}
    dfs(rt);
//  E(i,rt) cout<<to[i]<<" "<<endl;
//  F(i,1,n) cout<<i<<" "<<dp[i][0]<<" "<<dp[i][1]<<endl;cout<<endl;
//  F(i,1,n) cout<<i<<" "<<g[i][0]<<" "<<g[i][1]<<endl;cout<<endl;
    printf("%lld\n",max(dp[rt][0],dp[rt][1]));
    if(dp[rt][0]>dp[rt][1]) cout<<g[rt][0];
    else if(dp[rt][0]<dp[rt][1]) cout<<g[rt][1];
    else cout<<g[rt][0]+g[rt][1];
    return 0;
}

高精版:坑

20180723 考試記錄