• 【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
    ",ans);
        return 0;
    }
    T3

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

    自己要加油啊!!!

  • 相关阅读:
    对象实例化过程分析
    对象实例化过程分析
    QuickHit游戏
    QuickHit游戏
    java继承向上转型和向下转型和动态绑定
    java继承向上转型和向下转型和动态绑定
    洛谷:P1095 守望者的逃离(贪心+dp)
    Manacher算法-最长回文子串
    numpy array()
    CNN 卷积神经网络结构
  • 原文地址:https://www.cnblogs.com/JKAI/p/7411405.html
Copyright © 2020-2023  润新知