【SRM15】题解

恭喜TJM和CYC成功ak!!!%%%

终于又补完一次SRM的题啦蒟蒻选手终于可以发题解辣~

 


 

 

蒟蒻选手比赛经过(dalao可以直接跳过这段):

8:30比赛开始

咦第一题,模拟?dp?

再看一眼,靠,裸的线段覆盖,贪心啊。十分钟码完调完(really?),8:57提交,过!

t2是什么鬼?网络流?好像有点像啊(误,可是怎么建图啊(接着挣扎了半个小时),诶好像可以这么建,试一试!

五分钟码完调,诶怎么回事总是输出n*A?样例都过不了啊qvq。

再一看建的图,我去这建图方式从头错到尾啊。

完,陷入僵局。

心灰意冷地再看一眼,woc,sb最小生成树,还是模板......弱智地赶紧码完过样例就交。此时10:08。

t3是什么东西(弱智++),想起了NOIP2005的篝火晚会?(事实证明两者毫无关系)啊环形的题目我最怕了QAQ,于是各种脑洞大开,什么树状数组、环形dp想了个遍,挣扎一个多小时最后三分钟交了个n方暴力就跑...

预测分数:100+100+30=230

实际分数:60+40+30=130

啊啊啊t1和t2怎么都挂了QAQ。然后就陷入了艰苦卓绝的找错误阶段——

最后发现,t1少打了个+1,t2枚举上界和并查集合并集合写错,惨......%>_<%

 


 

 

好的终于水完了,可以开始发题解了...

T1

题目链接

看出是线段覆盖就没什么难的了,排完序贪一下心就可以了,注意两边区间都是闭的所以+1什么的别打漏...

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mem(a) memset(a,0,sizeof(a))
typedef long long LL;
const int N=5e5+7;
using namespace std;
int n;
struct node{
    int a,b;
}e[N];
int read()
{
    int ans=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    return ans*f;
}
bool cmp(node c,node d){return c.a<d.a||(c.a==d.a&&c.b>d.b);}
int main()
{
    n=read();int ai;
    for(int i=1;i<=n;i++){
        ai=read();
        e[i].a=max(1,i-ai);
        e[i].b=min(n,i+ai);
    }
    sort(e+1,e+1+n,cmp);
    int sum=1,x=e[1].b;
    for(int i=1;i<=n;i++){
        if(x==n)break;
        if(e[i].a>x){
            sum++;
            x=e[i].b;
            continue;
        }
        int x0=x;
        for(int j=i;j<=n;j++){
            if(e[j].a>x+1)break;
            if(e[j].b<=x0){i=j;continue;}
            x0=e[j].b;
            i=j;
        }
        if(x<x0){x=x0;sum++;}
    }
    printf("%d",sum);
    return 0;
}
T1

 

T2

题目链接

每个顶点先向0连一条权值为A的边,再两两之间连一条权值为B*两点曼哈顿距离的边,排完序跑一次Kruskal就行啦。

#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long LL;
const int N=1e3+5,inf=0x3f3f3f3f;
using namespace std;
struct node{
    int w,from,to;
}e[1000100];
int n,s=0,A,B,tot=0;
int xi[N],yi[N],fa[N];
int read()
{
    int ans=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    return ans*f;
}
void add(int u,int v,int w)
{
    tot++;e[tot].from=u;e[tot].to=v;e[tot].w=w;
}
bool cmp(node a,node b){return a.w<b.w;}
int getf(int x)
{
    if(fa[x]==x)return x;
    fa[x]=getf(fa[x]);
    return fa[x];
}
int main()
{
    int ans=0; 
    n=read();A=read();B=read();
    for(int i=0;i<=n;i++)fa[i]=i;
    for(int i=1;i<=n;i++){
        xi[i]=read();yi[i]=read();fa[i]=i;
        add(s,i,A);
        for(int j=1;j<i;j++){
            int x=abs(xi[i]-xi[j])+abs(yi[i]-yi[j]);
            add(i,j,B*x);
        }
    }
    sort(e+1,e+1+tot,cmp);
    int k=0;
    for(int i=1;i<=tot;i++){
        int x=e[i].from,y=e[i].to;
        if(getf(x)!=getf(y)){
            fa[fa[y]]=fa[x];
            ans+=e[i].w;
            k++;
        }
        if(k>=n)break;
    }
    printf("%d",ans);
    return 0;
}
T2

 

T3

题目链接

比赛时自己是没想出来的,最后是请教cyc dalao才会的(orz cyc><),这里直接甩一波他的题解:

假设当前si>i的数量为A,往左移的话就ans++,当前si<i的数量为B,往左移就ans--,所以每次ans+=A-B,
然后当si=i时,就会由A变B,记录是在哪一轮发生的
每轮在把一个B变A(调到后面)在做对应的答案变化

这里我们用b[i]来表示在第i次旋转操作时A变B的si的个数

注意,每次ans+(A-B)时,我们是默认原来与i=1匹配的那个s[j]现在匹配给了i=0,而实际上此时的s[j]应当匹配i=n,所以ans还要先减去s[j](s[j]-0)再加上n-s[j](s[j]一定小于或等于n)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
typedef long long LL;
const int N=2e6+10;
using namespace std;
int n,si[N],b[N],A=0,B=0;
int read()
{
    int ans=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();}
    return ans*f;
}
int main()
{
    n=read();LL ans=0;
    for(int i=1;i<=n;i++){
        si[i]=read();
        ans+=abs(si[i]-i);
        if(si[i]<i){
            B++;
            b[i-si[i]]++;
        }
        else{
            A++;
            b[i+n-si[i]]++;
        }
    }
    LL anss=ans;
    for(int i=1;i<=n-1;i++){
        anss+=A-B-si[i]+n-si[i];
        A--;B++;A+=b[i];B-=b[i];
        ans=min(ans,anss);
    }
    printf("%lld\n",ans);
    return 0;
}
T3

 


 

 

其实这一场SRM的题目并不难(好吧除了T3),可以说出题人是灰常灰常良心的。然而就是这些基础的东西我都没能做好。如今NOIP2017只剩80天了,如果不想留下遗憾的话,这种事情以后绝对不能再发生了啊!

自己要加油啊!!!

 

转载于:https://www.cnblogs.com/JKAI/p/7411405.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值