zoukankan      html  css  js  c++  java
  • goj 买粽子(UVA唯一的雪花)

    Problem Description:

    端午节快到了,小蛋准备到集市上买粽子。于是周六这天,小蛋和舍友搭着公交到了西南市场。说来也怪,这天集市上就只有n个人在卖粽子,整齐地排成一列,而且第i(1<=i<=n)个人前面有Xi个粽子堆在一起。小蛋这人平时很大方,买东西也很讲究,这次就想自掏腰包,准备买很多粽子送给同学和老师们吃。那么问题来了,有n个人在卖粽子,怎么个买法呢?小蛋就想在n个人中连续地选择k个相邻的人买他们全部的粽子,要求所选的这k个连续相邻的人各自卖的粽子数量不能有相同的个数,并且使得k最大。

    Input:

    输入有多组数据
    第一行输入一个整数n(0<n<=100000),表示集市上有n个人在卖粽子。
    第二行输入n个整数,第i个数表示第i个人卖的粽子数量Xi(0 < Xi <= 1000)。
    

    Output:

    输出符合条件的最大值k,每个输出占一行

    Sample Input:

    7
    3 2 4 1 3 2 3
    5
    1 6 3 1 2
    

    Sample Output:

    4
    4
    解题思路:滑动窗口,尺取法思想。找到一个最长的连续子序列,使得里面的元素都不相同。set容器维护,时间复杂度是O(nlog(n))。紫书讲得好:假设序列元素从0开始编号,所求连续子序列的左端点为L,右端点为R。从R=0开始不断增加R,相当于把所求序列的右端点往右延伸。当无法延伸(即A[R+1]在子序列A[L~R]中出现过)时,只需增大L,并且继续延伸R。既然当前的A[L~R]是可行解,L增大之后必然还是可行解,所以不必减少R,继续增大即可。
    AC代码一之set:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e5+5;
     4 int n,x[maxn],l,r,ans;set<int> st;
     5 int main(){
     6     while(~scanf("%d",&n)){
     7         for(int i=0;i<n;++i)scanf("%d",&x[i]);
     8         l=r=ans=0;st.clear();
     9         while(r<n){
    10             while(r<n&&!st.count(x[r]))st.insert(x[r++]);
    11             ans=max(ans,r-l);
    12             st.erase(x[l++]);
    13         }
    14         printf("%d
    ",ans);
    15     }
    16     return 0;
    17 }
    AC代码二之map:思路和操作跟上面一样,非常巧妙地处理了区间中不同元素的下标。
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e5+5;
     4 int n,l,r,ans,x,last[maxn];map<int,int> cur;
     5 int main(){
     6     while(~scanf("%d",&n)){
     7         memset(last,0,sizeof(last));cur.clear();
     8         for(int i=0;i<n;++i){
     9             scanf("%d",&x);
    10             if(!cur.count(x))last[i]=-1;///如果还没出现,则标记为-1
    11             else last[i]=cur[x];///否则记录上一次出现的下标
    12             cur[x]=i;///更新当前x的坐标
    13         }
    14         l=r=ans=0;
    15         while(r<n){
    16             while(r<n&&last[r]<l)r++;///如果当前last[r]!=l说明该区间中所有元素都不同,则继续向右延伸r,否则l++,即左端点向右蠕动
    17             ///cout<<l<<endl;
    18             ans=max(ans,r-l);
    19             l++;
    20         }
    21         printf("%d
    ",ans);
    22     }
    23     return 0;
    24 }
    25 /*
    26 i        0  1  2  3  4  5  6
    27 A[i]     3  2  4  1  3  2  3
    28 last[i] -1 -1 -1 -1  0  1  4
    29 */
    
    
  • 相关阅读:
    XMPP协议的原理介绍
    ExtJs自学教程(1):一切从API開始
    开源阅读器
    查询记录时rs.previous()的使用
    C/C++产生随机数
    探索WebKit内核(一)------ 菜鸟起步
    Qt编写串口通信程序全程图文解说
    超过响应缓冲区限制
    数据库原理 知识点总结
    http 双向通信之port映射
  • 原文地址:https://www.cnblogs.com/acgoto/p/9215475.html
Copyright © 2011-2022 走看看