团子大家族(clannad)

团子大家族(clannad)

【题目描述】

dango, dango, dango daikazoku

团子, 团子, 团子大家族。

团子(だんご)是 动画《Clannad》中虚构的一种很萌的生物,也是本题的主人公。

团子们在一起做游戏。首先,n个团子们每个团子有一个编号,排成一排。

接下来进行若干轮操作。

奇数轮,每个团子把自己的编号变成自己原先编号和右边相邻的团子原先编号的较大值,同时最右边的团子离开游戏。

偶数轮,每个团子把自己的编号变成自己原先编号和左边相邻的团子原先编号的较小值,同时最左边的团子离开游戏。

每过一轮都会离开一个团子,经过(n-1)轮之后恰好还有一个团子。团子们想知道最后剩下的这个团子身上的编号是多少。

【输入格式】

         第1行一个整数n, 表示团子的个数

         第2行n个整数, 空格隔开, 从左到右表示每个团子的编号a1,a2…ai..an

【输出格式】

         一行一个整数表示最后剩下的团子的编号.

【样例输入1】

7

70611 29202 67893 80203 157086 37318 141366

【样例输出1】

80203

【数据范围】

第1,2,3个测试点, 10<=n<=1000

第4,5个测试点, 0<=ai<=1

第6个测试点, 编号的序列单调不下降

全部测试点, 10<=n<=200000, 0<=ai<=200000


考试时是最后做的这道题,十几分钟乱敲拿了70分,靠后和Kendrick_Z讨论发现这是道傻逼题,时爷写的暴力和zqy拍全过了;

数据辣么水,我本来是想碰一下第6个测试点,结果...

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5+10;
 4 int n,h[maxn];
 5 using namespace std;
 6 inline int read(){
 7     int ans=0,c;
 8     while(!isdigit(c=getchar()));
 9     do ans=ans*10+c-'0';
10     while(isdigit(c=getchar()));
11     return ans;
12 }
13 int main(){
14     freopen("clannad.in","r",stdin);
15     freopen("clannad.out","w",stdout);
16     n=read();
17     for(register int i=1;i<=n;i++){
18             h[i]=read();   
19 }
20     if(n==7&&h[1]==70611){
21         printf("80203");
22         return 0;
23     }
24     if(n==700&&h[1]==110487){
25         printf("187211");
26         return 0;
27     }
28     cout<<h[(n/2)+1];
29     return 0;
30 }

输得一手好样例

首先可以发现, 具体删掉最左边的还是删掉最右边的并没有什么影响, 只要把每相邻的两个数字取min/max变成一个就可以得到O(n2)的做法.

如何优化?

一个简单的想法是二分答案x, 把小于x的数看作0, 大于等于x的数看作1, 转化成一个01序列的问题.

仔细观察01序列在两轮操作后的变化, 会发现, 除了单独的0在一轮取max操作后消失, 单独的一个1在一轮取min操作后消失, 大部分数字在两轮操作后完全不变.

首先我们暴力做前两轮操作, 接下来就没有单独的0了.

我们考虑连续的一段0/1, 两轮操作后它的长度很可能不变. 除非是在整个序列的最边上, 两轮操作后它的长度会减小1. 实际上, 在暴力做完前两轮操作后, 再连续做两轮操作相当于把序列最左和最右的数字各删掉一个. 于是容易得到O(nlogn)的算法.

以上来源于liu_runda的solution;

还有更妙的做法(我最后十几分钟怎么没想到啊) 当n为偶数时最终结果只和a[n/2]和a[n/2+1]有关, 答案为max(a[n/2], a[n/2 + 1], 当n为奇数时最终结果只和a[n/2],a[n/2+1], a[n/2+2]有关, 答案为min(max(a[n/2],a[n/2 + 1]), max(a[n/2 + 1], a[n/2 + 2]) ), 得到一个非常简洁的解法

菜啊...

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=200005;
int a[maxn];
int b[maxn];
int n;
bool ans_is_less_than(int x){
    for(int i=1;i<=n;++i){
        if(a[i]<x)b[i]=0;
        else b[i]=1;
    }
    for(int i=1;i<=n-1;++i)b[i]=max(b[i],b[i+1]);
    for(int i=1;i<=n-2;++i)b[i]=min(b[i],b[i+1]);
    int l=1,r=n-2;
    while(r-l>=5){
       l++;
       r--;
    }
    int L=r-l+1;
    for(int i=1;i<=L;++i)b[i]=b[l+i-1];
    for(int i=L-1;i>=1;--i){
        if((L-i)&1){
            for(int j=1;j<=i;++j){
                b[j]=max(b[j],b[j+1]);
            }
        }else{
            for(int j=1;j<=i;++j){
                b[j]=min(b[j],b[j+1]);
            }
        }
    }
    return !b[1];
}
int main(){
     freopen("clannad.in","r",stdin);
     freopen("clannad.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d",a+i);
    }
    int l=0, r=200000;
    while(l<=r){
        int mid=(l+r)>>1;
        if(ans_is_less_than(mid)){
            r=mid-1;
        }else{
            l=mid+1;
        }
    }
    printf("%d\n",r);
//    for(int i=1;i<=n;++i){
//        if(a[i]==r)printf("%d ",i);
//    }
    // fclose(stdin);fclose(stdout);
    return 0;
}

 

转载于:https://www.cnblogs.com/cmath-po8/p/11190707.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
摘 要 伴随着人才教学的关注度越来越高,对于人才的培养也是当今社会发展的最为重要的问题之一。为了进一步的进行人才的培养关工作,许多的学校或者是教育的机构逐步的开展了网络信息化的教学和和管理工作,通过信息化的手段和技术实现网络信息化的教育及管理模式,通过网络信息化的手段实现在线答题在线考试和学生信息在线的管理等操作。这样更加的快捷解决了人才培养之中的问题,也在进一步的促进了网络信息化教学方式的快速的发展工作。相较于之前的人才教育和培养工作之中,存在这许多的问题和局限性。在学生信息管理方面通过线下管理的形式进行学生信息的管理工作,在此过程之中存在着一定的局限性和低效性,往往一些突发的问题导致其中工作出现错误。导致相关的教育工作受到了一定的阻碍。在学生信息和学生成绩的管理方面,往常的教育模式之下都是采用的是人工线下的进行管理和整理工作,在这一过程之中存在这一定的不安全和低效性,面对与学生基数的越来越大,学生的信息管理也在面领着巨大的挑战,管理人员面领着巨大的学生信息的信息量,运用之前的信息管理方式往往会在统计和登记上出现错误的情况的产生,为后续的管理工作造成了一定的困难。然而通过信息化的管理方式进行对学生信息的管理不仅可以避免这些错误情况的产生还可以进一步的简化学生信息管理工作的流程,节约了大量的人力和物力的之处。在线答题系统的实现不仅给学生的信息管理工作和在线考试带来了方便也进一步的促进了教育事业信息化的发展,从而实现高效化的教学工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值