zoukankan      html  css  js  c++  java
  • [luogu7078]贪吃蛇

    结论:若$a_{n}-a_{1}ge a_{2}$,那么一定会吃掉

    证明:分类讨论,若$a_{n-1}$也吃掉了$a_{2}$,就说明$a_{n-1}$之后不会被吃掉,而$a_{n-1}-a_{2}le a_{n}-a_{1}$,因此$a_{n}$也不会被吃掉;若$a_{n-1}$不吃$a_{2}$,那么$a_{n}$同样也不会被吃掉

    (注意,这只是说明满足这一条件下一定会吃,而不是吃一定要满足此条件)

    根据这个结论,可以模拟直至$a_{n}-a_{1}<a_{2}$

    考虑接下来是否会吃,如果有$a_{n-1}-(a_n-a_{1})ge a_{2}$,那么一定不会吃(吃了$a_{n-1}$就一定可以吃他),类似的,如果$a_{n-1}-a'_{1}<a_{2}$且$a_{n-2}-a''_{1}ge a_{2}$,那么一定可以吃(因为$a_{n-1}$一定不会吃)……

    换言之,$a_{n}$吃掉$a_{1}$当且仅当下一次出现$a_{n'}-a_{1}ge a_{2}$时$n$与$n'$同奇偶,正确性可以归纳得到,同时下一次$n-1$与$n'$就不同奇偶了,即不能吃掉

    如何维护这个过程,对两部分分别维护:

    1.对于第一部分,即每一次都有$a_{n}-a_{1}<a_{2}$,将所有点分为经过操作和未经过操作两部分,根据上面证明的过程,越晚经过操作的越小,因此用一个队列维护两部分,最小值和最大值都可以得到

    2.对于第二部分,直接令$a_{1}=a_{n}-a_{1}$即可(当然要判断一下)

    还有一些特殊情况,主要是关于$n=2$时的判断

    1.对于第一部分,即模拟直到$a_{n}-a_{1}<a_{2}$,若最终$n=2$,则答案为1(可证一定有$a_{n}ge sum_{i=1}^{n-1}a_{i}$);

    2.对于第二部分,即模拟直到$a_{n}-a_{1}ge a_{2}$,若最终$n'=1$,令$n'=2$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 1000005
     4 #define fi first
     5 #define se second
     6 set<pair<int,int> >s;
     7 deque<pair<int,int> >q1,q2;
     8 int t,n,m,x,y,a[N];
     9 pair<int,int> b[N];
    10 int calc(int n){
    11     q1.clear(),q2.clear();
    12     for(int i=1;i<=n;i++)q1.push_back(make_pair(a[i],i));
    13     pair<int,int>x,y,z;
    14     while (1){
    15         if (n==2)return 1;
    16         if ((q2.empty())||(q1.back()>q2.back())){
    17             x=q1.back();
    18             q1.pop_back();
    19         }
    20         else{
    21             x=q2.back();
    22             q2.pop_back();
    23         }
    24         y=q1.front();
    25         q1.pop_front();
    26         z=make_pair(x.fi-y.fi,x.se);
    27         if (((q1.empty())||(q1.front()>z))&&((q2.empty())||(q2.front()>z))){
    28             q1.push_front(y);
    29             q1.push_back(x);
    30             break;
    31         }
    32         n--;
    33         q2.push_front(z);
    34     }
    35     int nn=0;
    36     while ((!q1.empty())||(!q2.empty()))
    37         if ((!q1.empty())&&((q2.empty())||(q1.front()<q2.front()))){
    38             b[++nn]=q1.front();
    39             q1.pop_front();
    40         }
    41         else{
    42             b[++nn]=q2.front();
    43             q2.pop_front();
    44         }
    45     while (nn>2){
    46         x=make_pair(b[nn].fi-b[1].fi,b[nn].se);
    47         if (x>=b[2])break;
    48         b[1]=x;
    49         nn--;
    50     }
    51     return n-((n&1)==(nn&1));
    52 }
    53 int main(){
    54     scanf("%d%d",&t,&n);
    55     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    56     printf("%d
    ",calc(n));
    57     t--;
    58     while (t--){
    59         scanf("%d",&m);
    60         for(int i=1;i<=m;i++){
    61             scanf("%d%d",&x,&y);
    62             a[x]=y;
    63         }
    64         printf("%d
    ",calc(n));
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    Android studio开发找不到HttpClient问题
    Android studio开发找不到HttpClient问题
    互联网应用之传递HTTP参数
    互联网应用之传递HTTP参数
    计算机组成原理
    计算机组成原理
    【NYOJ】[40]公约数和公倍数
    【NYOJ】[40]公约数和公倍数
    【NYOJ】[39]水仙花数
    【NYOJ】[39]水仙花数
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14026340.html
Copyright © 2011-2022 走看看