zoukankan      html  css  js  c++  java
  • 【问题描述】

      一张长度为的纸带,我们可以从左至右编号为(纸带最左端标号为)。现在有次操作,每次将纸带沿着某个位置进行折叠,问所有操作之后纸带的长度是多少。

    【输入格式】

      第一行两个数字如题意所述。

      接下来一行个整数代表每次折叠的位置。

    【输出格式】

      一行一个整数代表答案。

    【样例输入】

      5 2

      3 5

    【样例输出】

      2

    【样例解释】

      树上有只鸟。

    【数据规模与约定】

      对于60%的数据,N,M<=3000.

      对于100%的数据,N<=10^18,M<=3000.

    【题目分析】

      考场上用了并查集,就是把每次折叠后把这些点的父亲节点改为重合的最小的那个点,这样每一个点的父亲节点都是连续的,并查集啊,10^18你并查集个头啊...,无奈,脑子不好想不到正解

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    using namespace std;
    int n,m;
    int father[5001];
    int len=0;
    int x;
    int Find(int q) //寻找根节点 
    {
        if(father[q]==q) return q;
        else return father[q]=Find(father[q]);
    }
    int main()
    {
        freopen("he.in","r",stdin);
        freopen("he.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++)
            father[i]=i;
        int l=0,r=n;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&x);
            int fa=Find(x);
            if(fa-l>=r-fa)
            {
                len=fa-l;
                for(int j=1;j<=r-fa;j++)
                    father[fa+j]=father[fa-j];
                r=fa;
            }
            else
            {
                len=r-fa;
                for(int j=1;j<=fa-l;j++)
                    father[fa-j]=father[fa+j];
                l=fa;
            }
        }
        printf("%d",len);
        fclose(stdin);fclose(stdout);
        return 0;
    }
    辣鸡lemon的并查集

      事实上,用离线的做法每次折叠后把后面的折叠的编号都改变,取长的那段区间直接求......(一直理解错了那个a的含义.编号改变后都在长度之内..)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define ll long long
    using namespace std;
    ll n;
    int m;
    ll a[3010];
    ll abss(ll x)
    {
        return x<0?-x:x;
    }
    int main()
    {
        freopen("he.in","r",stdin);
        freopen("he.out","w",stdout);
        scanf("%I64d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%I64d",&a[i]);
        for(int i=1;i<=m;i++)
        {
            int flag=0;
            if(a[i]<(n+1)/2) flag=1;
            for(int j=i+1;j<=m;j++)
            {
                if(flag==1)
                    a[j]=abss(a[i]-a[j]);
                else if(a[j]>a[i])
                    a[j]=a[i]*2-a[j];
            }
            n=max(a[i],n-a[i]);
        }
        printf("%I64d",n);
        fclose(stdin);fclose(stdout);
        return 0;
    }
    上帝JustPenz233
  • 相关阅读:
    数据库创建用户SQL
    团队总结和展示
    第十三周总结
    梦断代码02
    第十二周进度博客
    团队冲刺第十五天
    团队冲刺第十四天
    团队冲刺第一阶段评价
    梦断代码01
    第十一周进度博客
  • 原文地址:https://www.cnblogs.com/xiaoningmeng/p/6033623.html
Copyright © 2011-2022 走看看