7年OI一场空,一句assert见祖宗。

题解

考虑一条蛇什么时候会叫停。

如果它吃了之后不是最小的,那么下一个吃了之后一定比它小(指以id为第二关键字后),死的一定比它早,那么可以直接吃,然后把问题交给下一条蛇即可。

如果吃了之后是最小的,那么下一个有可能吃它,那么它吃不吃就和下一条吃不吃相关,也就是和到之后第一次吃了不是最小的 的距离奇偶性相关了。

前面一部分显然满足后一个吃了之后比它小。后面(除了最后一次)也满足吃了之后会变成最小的。

那么再用一个队列,用类似「noip2016 蚯蚓」的方法维护即可。

时间复杂度$O(n)$,并且在$a_i$不满足不降的情况下应该也是对的。

然而我加了个错误的assert,然后就挂了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
#define x first
#define y second
int n;
int a[1000005];
namespace run{
    pii w1[1000005],w2[1000005];
    pii *l1,*r1,*l2,*r2;
    const pii inf(0x3f3f3f3f,0x3f3f3f3f),ind(-0x3f3f3f3f,-0x3f3f3f3f);
    pii mx1(){return l1<=r1?*l1:ind;}
    pii mn1(){return l1<=r1?*r1:inf;}
    pii mx2(){return l2<=r2?*l2:ind;}
    pii mn2(){return l2<=r2?*r2:inf;}
    int cnt,cur;
    bool add0(){
        if(~cur){cur^=1;}
        else{cur=0;}
        return 0;
    }
    bool add1(){
        if(~cur){cnt+=cur;return 1;}
        ++cnt;return 0;
    }
    void solve(){
        l2=w2+1;r2=w2;
        l1=w1+1;r1=w1+n;
        for(int i=1;i<=n;++i){
            w1[n+1-i].x=a[i];w1[n+1-i].y=i;    
        }
        cnt=0;cur=-1;
        int s=n;
        while(s>1){
            pii mx,mn;
            if(mx1()>mx2()){mx=mx1();++l1;}
            else{mx=mx2();++l2;}
            if(mn1()<mn2()){mn=mn1();--r1;}
            else{mn=mn2();--r2;}
            mx.x-=mn.x;
            --s;
            //assert(mx<mn2()); 这里显然是错的,因为从最小变成不是最小的时候不一定比第二小小。
            if(s>1 && mx<min(mn1(),mn2())){
                if(add0())return;
            }
            else{
                if(add1())return;
            }
            *(++r2)=mx;
/*            if(add0())return;
            if(add1())return;*/
        }
    }
    bool main(){
        solve();
        printf("%d\n",n-cnt);
        return 0;
    }
}
int main(){
    freopen("snakes.in","r",stdin);
    freopen("snakes.out","w",stdout);
    int t;
    scanf("%d",&t);
    for(int id=1;id<=t;++id){
        if(id==1){
            scanf("%d",&n);
            for(int i=1;i<=n;++i)scanf("%d",a+i);
        }
        else{
            int k,x;
            scanf("%d",&k);
            for(;k;--k){
                scanf("%d",&x);    
                scanf("%d",a+x);
            }
        }
        run::main();
    }
    return 0;
}

标签: none

添加新评论