2017-10-10离线赛总结

失分小结:
估分:200+
实际分数:200

考试过程:
第一题算是近几场中打起来较麻烦的,但理清关系还是简单的
第二题打的也十分流畅,先2n 枚举水30,再暴力n4dp
前缀和优化到n3再到n2,然后对拍
这时离考试结束还有两个半小时
第三题先是打了暴力,感觉不是特别好,但也没有去检查它的正确性
模拟了一下发现就是个路径压缩,就开始敲,快交的的时候才调过样例,
自己对拍的时候错误百出。。。
考完才发现暴力敲错了,正解最小生成树把m打成了n。。。
痛失100(╯°Д°)╯︵┻━┻

小结:考试别总是想着正解正解。。暴力对了再说,不然敲完也没法保证正确性

题解:
第一题:
一道搜索题,
听说好多人都卡在memset上了┓( ´-` )┏
较为简单的做法是先求联通块,分别给他们染色,并记录每种颜色连通块的个数
枚举把那个变成“.”看上下左右是否有连通块,然后把颜色不同的连通块个数相加就好了


第二题:
如果做过完美队形,这道题其实是很简单的,
这道题的动态规划很显然,而且是一道区间dp
二维的初始dp就是:

dp[i][j]=dp[h][k]+1{ h[1,i],k[j,n]&&i!=j }
ans+=dp[i][j]+dp[h][k]{ i==j }

第二条式子表示取i这个点作为回文子串的中点的方案数
dp[i][j]表示从1取到i从n取到j的子串方案数
然后不难发现dp[h][k]是可以前缀和处理的,然后复杂度就会由
n4降到n2
具体代码实现:

int dp[2005][2005];
int Sum[2005][2005];
void solve(){
    memset(dp,0,sizeof(dp));
    int ans=0;
    FOR(i,1,n){
        FOR(j,i,n){
            if(A[i]==A[j]&&i!=j){
                dp[i][j]=Sum[i-1][j+1]+1;
                if(dp[i][j]>=P)dp[i][j]-=P;
            }
            if(i==j){
                ans++;
                ans+=Sum[i-1][j+1];
                if(ans>=P)ans-=P;
            }
            ans+=dp[i][j];
            if(ans>=P)ans-=P;
        }
        DOR(j,n,i){
            Sum[i][j]=Sum[i][j+1]+dp[i][j];//  j--n
            Sum[i][j]%=P;
        }
        FOR(j,i,n){
            Sum[i][j]+=Sum[i-1][j];
            Sum[i][j]%=P;
        }
    }
    printf("%d\n",ans);
}

第三题
首先生成最小生成树S(在所有边都有的情况下)
然后可得知:若把非这个最小生成树上的边删去,那么最后生成的最小生成树就是S,则这些非树边的答案就是S的权值

但若把S上的边删去,情况就不同了
假设能生成最小生成树,则只需加入一条边
设加入边的权值为a,S的权值为A,删除边的权值为b
则改变后的生成树的权值为A-b+a
可以发现对于一条S上的边,删除它后的生成树大小只与加入的边有关
定理一:要是生成树为最小生成树,则要加入的边最小

可证加入一条边后,在原最小生成树S上会构成一个环,删去还上任意一条边,都可形成一棵树,即:
定理二:加进去的边能更新其两端点到LCA上的任意边

我们根据边权从小到大排序,加入一条边后把其两端点到LCA路径上的所有点更新,根据定理一,得出
定理三:被更新的边已经是最优解,则不必在更新一遍

那么可以采用路径压缩(并查集)保证每条边只被更新一次

代码实现:

void dfs(int x,int f,int id,int v) {
    fa[0][x]=f;//记录x点的父亲 
    fa[1][x]=id;//记录x点到父亲这条边的编号 
    fa[2][x]=v;//记录x点到父亲这条边的边权 
    dep[x]=dep[f]+1;
    for(unsigned i=0; i<edge[x].size(); i++) {
        int y=edge[x][i].to;
        if(y==f)continue;
        dfs(y,x,edge[x][i].id,edge[x][i].v);
    }
}
int Find(int x) {return x==FA[x]?x:FA[x]=Find(FA[x]);}
void up(int &x,int v) {//并查集实现路径压缩 
    if(ans[fa[1][x]]==INF)ans[fa[1][x]]=Mi-fa[2][x]+v;
    FA[x]=fa[0][x];
    x=Find(x);
}
void LCA(int x,int y,int v) {
    while(x!=y) {
        if(dep[x]>dep[y])up(x,v);
        else up(y,v);
    }
}
int deal() {//最小生成树 
    sort(A+1,A+m+1,cmp);
    FOR(i,1,n)Fa[i]=i;
    int sum=0;
    FOR(i,1,m) {
        int x=A[i].x,y=A[i].y;
        int f1=find(x),f2=find(y);
        if(f1==f2)continue;
        Fa[f1]=f2;
        edge[x].pb((node1) {y,A[i].id,A[i].v});
        edge[y].pb((node1) {x,A[i].id,A[i].v});
        sum+=A[i].v;
        mark[A[i].id]=1;
    }
    return sum;
}
void solve() {
    FOR(i,1,m)ans[i]=INF;
    FOR(i,1,m) {
        scanf("%d %d %d",&A[i].x,&A[i].y,&A[i].v);
        A[i].id=i;
    }
    Mi=deal();
    FOR(i,1,n)FA[i]=i;
    dfs(1,0,0,0);
    FOR(i,1,m) {//若为非树边,进行更新 
        if(mark[A[i].id])continue;
        else {
            LCA(A[i].x,A[i].y,A[i].v);
            ans[A[i].id]=Mi;
        }
    }
    FOR(i,1,m) {//输出答案,若为INF,说明没有被更新过,即不存在最小生成树 
        if(ans[i]==INF)printf("%d\n",-1);
        else printf("%d\n",ans[i]);
    }
}
int main() {
    scanf("%d %d",&n,&m);
    solve();
    return 0;
}
乐播投屏是一款简单好用、功能强大的专业投屏软件,支持手机投屏电视、手机投电脑、电脑投电视等多种投屏方式。 多端兼容与跨网投屏:支持手机、平板、电脑等多种设备之间的自由组合投屏,且无需连接 WiFi,通过跨屏技术打破网络限制,扫一扫即可投屏。 广泛的应用支持:支持 10000+APP 投屏,包括综合视频、网盘与浏览器、美韩剧、斗鱼、虎牙等直播平台,还能将央视、湖南卫视等各大卫视的直播内容一键投屏。 高清流畅投屏体验:腾讯独家智能音画调校技术,支持 4K 高清画质、240Hz 超高帧率,低延迟不卡顿,能为用户提供更高清、流畅的视觉享受。 会议办公功能强大:拥有全球唯一的 “超级投屏空间”,扫码即投,无需安装。支持多人共享投屏、远程协作批注,PPT、Excel、视频等文件都能流畅展示,还具备企业级安全加密,保障会议资料不泄露。 多人互动功能:支持多人投屏,邀请好友加入投屏互动,远程也可加入。同时具备一屏多显、语音互动功能,支持多人连麦,实时语音交流。 文件支持全面:支持 PPT、PDF、Word、Excel 等办公文件,以及视频、图片等多种类型文件的投屏,还支持网盘直投,无需下载和转格式。 特色功能丰富:投屏时可同步录制投屏画面,部分版本还支持通过触控屏或电视端外接鼠标反控电脑,以及在投屏过程中用画笔实时标注等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值