2017.10.29离线赛总结

toy ——4130

思路:强模拟…

running ——4131

思路:暴力分还是挺多的,s=t,w=0,s=1,t=1,list时,满打满算还有80分,但功底还是差了点啊,实际上s=1,t=1时,暴力会超时,也就是说必须要用正解了。
仔细理解题意,一个玩家从a 到 b, 沿途到达点的时间为0,1,2,…,b-a,而每个点的观察员只在wi时观察,也就是说,若想要被观察员观察到,就必须是
wi+i 或 wi-i,那么这个就有点像树上差分了。

#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long 
#define INF 0x3f3f3f3f
#define N 300005
using namespace std;

int n,m;
struct node{
    int s,t,lca,dis;
}A[N];
vector<int>E[N],vis[N];
int w[N],ans[N],sum[N];
int D[N],fa[N],top[N],sz[N],son[N];

struct p1{
    void solve(){
        REP(i,1,m)ans[A[i].s]++;
        REP(i,1,n)printf("%d ",w[i]?0:ans[i]);
        puts("");
    }
}p1;
struct p2{
    int sum1[N],sum2[N];
    vector<int>vis1[N],vis2[N];
    void solve(){
        REP(i,1,m){
            int a=A[i].s,b=A[i].t; 
            if (a<=b){
                vis1[a].push_back(i);
                vis1[b+1].push_back(i);
            }else{
                vis2[b].push_back(i);
                vis2[a+1].push_back(i);
            }
        }
        REP(i,1,n){
            REP(j,0,vis1[i].size()-1){
                int k=vis1[i][j];
                if (A[k].s==i)sum1[A[k].s]++;
                else sum1[A[k].s]--;
            }
            REP(j,0,vis2[i].size()-1){
                int k=vis2[i][j];
                if (A[k].t==i)sum2[A[k].s]++;
                else sum2[A[k].s]--;
            }
            if (i-w[i]>=1) ans[i]+=sum1[i-w[i]];
            if (i+w[i]<=n) ans[i]+=sum2[i+w[i]];
        }
        REP(i,1,n-1)printf("%d ",ans[i]);
        printf("%d\n",ans[n]);
    }
}p2;
struct p3{
    void dfs(int x,int f){
        D[x]=D[f]+1;
        if(D[x]-w[x]>0)ans[x]-=sum[D[x]-w[x]];
        REP(i,0,E[x].size()-1){
            int y=E[x][i];
            if(y==f)continue;
            dfs(y,x);
        }
        REP(i,0,vis[x].size()-1)sum[A[vis[x][i]].s]++;
        if(D[x]-w[x]>0)ans[x]+=sum[D[x]-w[x]];
    }
    void solve(){
        REP(i,1,m)vis[A[i].t].push_back(i);
        dfs(1,0);
        REP(i,1,n)printf("%d ",ans[i]);
        puts("");
    }
}p3;
struct p4{
    void dfs(int x,int f){
        D[x]=D[f]+1;
        if (D[x]+w[x]<=n) ans[x]-=sum[D[x]+w[x]];
        REP(i,0,E[x].size()-1){
            int to=E[x][i];
            if (to==f) continue;
            dfs(to,x);
        }
        for (int i=0;i<(int)vis[x].size();i++)sum[D[A[vis[x][i]].s]]++;
        if (D[x]+w[x]<=n)ans[x]+=sum[D[x]+w[x]];
    }
    void solve(){
        REP(i,1,m)vis[A[i].s].push_back(i);
        dfs(1,0);
        REP(i,1,n)printf("%d ",ans[i]);
        puts("");
    }
}p4;
struct p5{
    struct Node{
        int op,dep;
    };
    vector<Node>Q1[N],Q2[N];
    int sum1[N],sum2[N*2];
    void dfs1(int x,int f){
        D[x]=D[f]+1;
        fa[x]=f;
        sz[x]=1;
        REP(i,0,E[x].size()-1){
            int y=E[x][i];
            if(y==f)continue;
            dfs1(y,x);
            sz[x]+=sz[y];
            if(sz[y]>sz[son[x]])son[x]=y;
        }
    }
    void dfs2(int x,int tp){
        top[x]=tp;
        if(son[x])dfs2(son[x],tp);
        REP(i,0,E[x].size()-1){
            int y=E[x][i];
            if(y==fa[x] || y==son[x])continue;
            dfs2(y,y);
        }
    }
    int Lca(int a,int b){
        while(top[a]!=top[b]){
            if(D[top[a]]<D[top[b]])swap(a,b);
            a=fa[top[a]];
        }
        return D[a]<D[b]?a:b;
    }
    void dfs(int x,int f){
        if(D[x]+w[x]<=n)ans[x]-=sum1[D[x]+w[x]];
        ans[x]-=sum2[D[x]-w[x]+N];
        REP(i,0,E[x].size()-1){
            int y=E[x][i];
            if(y==f)continue;
            dfs(y,x);
        }
        REP(i,0,Q1[x].size()-1){
            Node y=Q1[x][i];
            if(y.op)sum1[y.dep]++;
            else sum1[y.dep]--;
        }
        REP(i,0,Q2[x].size()-1){
            Node y=Q2[x][i];
            if(y.op)sum2[y.dep]++;
            else sum2[y.dep]--;
        }
        if(D[x]+w[x]<=n)ans[x]+=sum1[D[x]+w[x]];
        ans[x]+=sum2[D[x]-w[x]+N];
    }
    void solve(){
        dfs1(1,0);
        dfs2(1,1);
        REP(i,1,m){
            A[i].lca=Lca(A[i].s,A[i].t);
            A[i].dis=D[A[i].s]+D[A[i].t]-D[A[i].lca]*2;
            Q1[A[i].s].push_back((Node){1,D[A[i].s]});
            Q1[A[i].lca].push_back((Node){0,D[A[i].s]});
            Q2[A[i].t].push_back((Node){1,D[A[i].t]-A[i].dis+N});
            Q2[fa[A[i].lca]].push_back((Node){0,D[A[i].t]-A[i].dis+N});
        }
        dfs(1,0);
        REP(i,1,n)printf("%d ",ans[i]);
        puts("");
    }
}p5;
int main(){
//  freopen("running.in","r",stdin);
//  freopen("running.out","w",stdout);
    cin>>n>>m; 
    REP(i,1,n-1){
        int a,b;
        scanf("%d%d",&a,&b);    
        E[a].push_back(b);
        E[b].push_back(a);      
    }
    REP(i,1,n)scanf("%d",&w[i]);
    REP(i,1,m)scanf("%d%d",&A[i].s,&A[i].t);
    if(n==991 || n==992)p1.solve();// s=t w=0
    else if(n==99994)p2.solve();// list 
    else if(n==99995)p3.solve();// s=1
    else if(n==99996)p4.solve();// t=1
    else p5.solve(); // ac code 
    return 0;
}

classroom ——4132

思路:这题的暴力分也不少…,m=0,1,2时,满打满算也有68分(不赘述了),而正解显然是dp,但这里是期望dp。

#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long 
#define db double
#define N 2005
using namespace std;

int n,m,v,e;
int c[N],d[N];
db INF,p[N],dis[N][N],dp[N][N][2],ans;

void Floyd(){
    REP(k,1,v)
        REP(i,1,v)
            REP(j,1,v)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
struct p2{
    void solve(){
        db tot=1e15;
        REP(k,1,n){
            db sum=0;
            db p1=1-p[k];
            swap(c[k],d[k]);
            REP(i,2,n)sum+=dis[c[i-1]][c[i]]; 
            tot=min(tot,sum*p[k]+ans*p1);
            swap(c[k],d[k]);
        }
        printf("%.2lf\n",tot);
    }
}p2;
struct p3{
    void solve(){
        db tot=1e15;
        REP(k,1,n){
            REP(l,k+1,n){
                db sum=0,res=0;
                db p1=p[k]*p[l];
                db p2=p[k]*(1-p[l]);
                db p3=p[l]*(1-p[k]);
                db p4=1-p1-p2-p3;
                sum+=ans*p4;

                swap(c[k],d[k]);
                res=0;
                REP(i,2,n)res+=dis[c[i-1]][c[i]]; 
                sum+=res*p2; 
                swap(c[k],d[k]);

                swap(c[l],d[l]);
                res=0;
                REP(i,2,n)res+=dis[c[i-1]][c[i]]; 
                sum+=res*p3; 
                swap(c[l],d[l]);

                swap(c[k],d[k]);swap(c[l],d[l]);
                res=0;
                REP(i,2,n)res+=dis[c[i-1]][c[i]]; 
                sum+=res*p1; 
                swap(c[k],d[k]);swap(c[l],d[l]);

                tot=min(tot,sum);   
            }
        }
        printf("%.2lf\n",tot);
    }
}p3;    
struct pAC{
    void solve(){
        memset(dp,127,sizeof(dp));
        dp[1][0][0]=dp[1][1][1]=0;
        REP(i,1,n-1)
            REP(j,0,min(i,m)){
                if(dp[i][j][0]!=INF){
                    dp[i+1][j][0]=min(dp[i+1][j][0],dp[i][j][0]+dis[c[i]][c[i+1]]);
                    if (j<m)dp[i+1][j+1][1]=min(dp[i+1][j+1][1],dp[i][j][0]+dis[c[i]][c[i+1]]*(1-p[i+1])+dis[c[i]][d[i+1]]*p[i+1]);
                }
                if(dp[i][j][1]!=INF){
                    dp[i+1][j][0]=min(dp[i+1][j][0],dp[i][j][1]+dis[c[i]][c[i+1]]*(1-p[i])+dis[d[i]][c[i+1]]*p[i]);
                    if (j<m) dp[i+1][j+1][1]=min(dp[i+1][j+1][1],
                    dp[i][j][1]+(1-p[i])*(1-p[i+1])*dis[c[i]][c[i+1]]+(1-p[i])*p[i+1]*dis[c[i]][d[i+1]]+p[i]*(1-p[i+1])*dis[d[i]][c[i+1]]+p[i]*p[i+1]*dis[d[i]][d[i+1]]);
                }
            }
        REP(i,0,m)ans=min(ans,min(dp[n][i][0],dp[n][i][1]));
        printf("%0.2lf\n",ans);
    }
}p100;
int main(){
//    freopen("classroom.in","r",stdin);
//    freopen("classroom.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&v,&e);
    REP(i,1,n)scanf("%d",&c[i]);
    REP(i,1,n)scanf("%d",&d[i]);
    REP(i,1,n)scanf("%lf",&p[i]);
    memset(dis,127,sizeof(dis));
    INF=dis[0][0];
    REP(i,1,v)dis[i][i]=0;
    REP(i,1,e){
        int x,y;
        db z;
        scanf("%d%d%lf",&x,&y,&z);
        dis[x][y]=dis[y][x]=min(dis[x][y],z);
    }
    Floyd();
    REP(i,2,n)ans+=dis[c[i-1]][c[i]];
    if(!m)printf("%.2lf\n",ans);
    else if(m==1)p2.solve();
    else if(m==2 && n<10)p3.solve();
    else p100.solve();
}

小结:去年的暴力分真心是多,100+35+68=203,而其中第2题s=1,t=1稍微想想应该也就有45…看来代码的功底还有待提高呀…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值