zoukankan      html  css  js  c++  java
  • 【2016福建省夏令营Day1】数据结构

    Problem 1 楼房(build.cpp/c/pas)

    【题目描述】

    地平线(x轴)上有n个矩(lou)形(fang),用三个整数h[i],l[i],r[i]来表示第i个矩形:矩形左下角为(l[i],0),右上角为(r[i],h[i])。地平线高度为0。在轮廓线长度最小的前提下,从左到右输出轮廓线。

    下图为样例2。

    wps3B11.tmp

    【输入格式】

    第一行一个整数n,表示矩形个数。

    以下n行,每行3个整数h[i],l[i],r[i]表示第i个矩形。

    【输出格式】

    第一行一个整数m,表示节点个数。

    以下m行,每行一个坐标表示轮廓线上的节点。从左到右遍历轮廓线并顺序输出节点。第一个和最后一个节点的y坐标必然为0。

    【样例输入】

    2
    3 0 2
    4 1 3

    【样例输出】

    6
    0 0
    0 3
    1 3
    1 4
    3 4
    3 0

    【样例输入2】

    5
    3 -3 0
    2 -1 1
    4 2 4
    2 3 7
    3 6 8

    【样例输出2】

    14
    -3 0
    -3 3
    0 3
    0 2
    1 2
    1 0
    2 0
    2 4
    4 4
    4 2
    6 2
    6 3
    8 3
    8 0

    【数据范围】

    对于30%的数据,n<=100

    对于另外30%的数据,n<=100000,1<=h[i],l[i],r[i]<=1000

    对于100%的数据,1<=n<=100000,1<=h[i]<=10^9,-10^9<=l[i]<r[i]<=10^9

    题解

    扫描线+堆维护

    推荐使用multset和pair 很方便

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    using namespace std;
    
    pair<int,int> a[1000005],ans[1000005];
    multiset<int> q;
    int n,cnt,maxh,num;
    
    int main()
    {
        int i,j,h,x,y;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d%d%d",&h,&x,&y);
            a[++cnt]=make_pair(x,h);
            a[++cnt]=make_pair(y,-h);
        }
        sort(a+1,a+1+cnt);
        q.insert(0);
        maxh=0;
        for(i=1;i<=cnt;)
        {
            for(j=i;j<=cnt;j++)
            {
                if(a[i].first<a[j].first) break;
                else
                 if(a[j].second>0) q.insert(a[j].second);
                 else q.erase(q.find(-a[j].second));
            }
            h=*q.rbegin();
            if(h!=maxh)
            {
                ans[++num]=make_pair(a[i].first,maxh);
                ans[++num]=make_pair(a[i].first,h);
                maxh=h;
            }    
            i=j;
        }
        printf("%d
    ",num);
        for(i=1;i<=num;i++) printf("%d %d
    ",ans[i].first,ans[i].second);
        return 0;
    }

    Problem 2 单词背诵(word.cpp/c/pas)

    【题目描述】

    灵梦有n个单词想要背,但她想通过一篇文章中的一段来记住这些单词。

    文章由m个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下,还要使选出的文章段落尽量短,这样她就可以用尽量短的时间学习尽可能多的单词了。

    【输入格式】

    第一行一个数n,表示想要背的单词数。

    接下来n行每行是一个长度不超过10的字符串,表示一个要背的单词。

    接着是一个数m,表示文章中的单词数

    然后是m行长度不超过10的字符串,每个表示文章中的一个单词。

    【输出格式】

    输出文件共2行。第1行为文章中最多包含的要背的单词数,第2行表示在文章中包含最多要背单词的最短的连续段的长度。

    【样例输入】

    3

    hot

    dog

    milk

    5

    hot

    dog

    dog

    milk

    hot

    【样例输出】

    3

    3

    【数据范围】

    对于30%的数据 n<=50,m<=500;

    对于60%的数据 n<=300,m<=5000;

    对于100%的数据 n<=1000,m<=100000;

    题解

    哈希+双指针扫描

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define mod 233327
    using namespace std;
    
    int n,m,anscnt,ans,cnt;
    char s[15],str[100005][15];
    struct hh
    {
        char v[15];
        int next;
    };
    hh e[5005];
    int last[500005],hash[500005],vis[500005];
    bool h[500005];
    void insert(int x)
    {
        ++cnt;
        strcpy(e[cnt].v,s);
        e[cnt].next=last[x];
        last[x]=cnt;
    }
    
    bool query(int x,int k)
    {
        int i;
        for(i=last[x];i;i=e[i].next)
         if(!strcmp(e[i].v,str[k])) return true;
        return false;
    }
    
    int main()
    {
        int i,j,len,thash,head,tail,now,tlen;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("
    %s",&s);
            len=strlen(s);thash=0;
            for(j=0;j<=len-1;j++)
              thash=(thash*233+s[j])%mod;
            insert(thash); 
        }
        scanf("%d",&m);
        for(i=1;i<=m;i++)
        {
            scanf("
    %s",&str[i]);
            len=strlen(str[i]);thash=0;
            for(j=0;j<=len-1;j++)
             thash=(thash*233+str[i][j])%mod;
            hash[i]=thash;
        }
        for(i=1;i<=m;i++)
          if(query(hash[i],i)&&!h[hash[i]])
          {
              anscnt++;
              h[hash[i]]=true;
          }  
        printf("%d
    ",anscnt);
    
        if(!anscnt) goto hhh;
        head=1;tail=1;now=tlen=0;
        ans=100005;
        if(query(hash[1],1))
        {
            vis[hash[1]]=1;
            now++;
        }
        while((head<=tail&&tail<m)||now==anscnt)
        {
            if(now==anscnt)
            {
                ans=min(ans,tail-head+1);
                thash=hash[head++];
                if(query(thash,head-1))
                {
                    vis[thash]--;
                    if(!vis[thash]) now--;
                }
            }
            else
            {
                thash=hash[++tail];
                if(query(thash,tail))
                {
                    if(!vis[thash]) now++;
                    vis[thash]++;
                }
            }
        }
        hhh:;
        printf("%d",ans);
        return 0;
    }

    Problem 3 矩阵(matrix.cpp/c/pas)

    【题目描述】

    给定一个N行M列的非负整数矩阵,求一个最大的正方形子矩阵,该矩阵满足:

    矩阵中每一个元素权值都大于0;

    在满足上述条件的前提下,矩阵面积最大;

    在满足上述条件的前提下,选择元素和最小的。

    【输入格式】

    第一行两个整数N, M

    接下来N行,每行M个整数。

    【输出格式】

    两个数,用空格隔开,第一个数为满足条件的矩阵的面积,第二个数为该矩阵各元素之和。

    【样例输入】

    3 7

    1 1 1 0 2 1 1

    1 1 1 0 1 1 1

    1 1 1 0 1 1 1

    【样例输出】

    9 9

    【数据范围】

    对于30%的数据,R,C<=10;

    对于60%的数据,R,C<=100;

    对于100%的数据,R,C<=1000。

    0 <= 输入的其他整数 <= 10^9

    题解

    一开始预处理前缀和,然后二分正方形边长,枚举正方形的位置即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    int n,m,a[1005][1005],ans1;
    long long sum[1005][1005],sum0[1005][1005],ans2=1LL<<60;
    bool checkzero(int x,int y,int len)
    {
        int newx,newy;
        newx=x+len-1,newy=y+len-1;
        return sum0[newx][newy]-sum0[x-1][newy]-sum0[newx][y-1]+sum0[x-1][y-1]==0;
    }
    
    bool check(int len)
    {
        int i,j;
        for(i=1;i+len-1<=n;i++) 
          for(j=1;j+len-1<=m;j++)
            if(checkzero(i,j,len)) return true;
        return false;
    }
    int main()
    {
        int i,j,nowsum0,l,r,mid,nowi,nowj;
        long long nowsum;
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++) 
          for(j=1;j<=m;j++) 
            scanf("%d",&a[i][j]);
        for(i=1;i<=n;i++)
        {
            nowsum=0LL;
            nowsum0=0;
            for(j=1;j<=m;j++)
            {
                nowsum+=a[i][j];
                nowsum0+=a[i][j]==0;
                sum[i][j]=sum[i-1][j]+nowsum;
                sum0[i][j]=sum0[i-1][j]+nowsum0;
            }
        }
        l=1;
        r=n<m?n:m;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(check(mid))
            {  
               ans1=mid;
               l=mid+1;
            }
            else r=mid-1;
        }
        printf("%d ",ans1*ans1);
        
        for(i=1;i+ans1-1<=n;i++) 
          for(j=1;j+ans1-1<=m;j++)
            if(checkzero(i,j,ans1))
            {
                nowi=i+ans1-1;
                nowj=j+ans1-1;
                ans2=min(ans2,sum[nowi][nowj]-sum[i-1][nowj]-sum[nowi][j-1]+sum[i-1][j-1]);
            }
        printf("%lld",ans2);
        return 0;
    }
  • 相关阅读:
    【Android】自带Theme
    【网络】SSH
    【Android】录音暂停和继续
    【Android】屏幕翻转(screen orientation change)
    【Android每日一讲】2012.10.31 关于(about)程序信息 Menu功能菜单程序设计
    [Android Samples视频系列之ApiDemos] AppActivityFinish Affinity
    初识移动互联网
    [Android Samples视频系列之ApiDemos] AppActivityHello world
    【Android每日一讲】2012.10.29 控制不同的文字字体 Typeface对象使用
    [Android Samples视频系列之ApiDemos] AppActivityIntentActivityFlags
  • 原文地址:https://www.cnblogs.com/yljiang/p/5758004.html
Copyright © 2011-2022 走看看