[luogu7078]貪吃蛇

結論:若$a_{n}-a_{1}\ge a_{2}$,那麼必定會吃掉c++

證實:分類討論,若$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}$一樣也不會被吃掉ide

(注意,這只是說明知足這一條件下必定會吃,而不是吃必定要知足此條件)spa

根據這個結論,能夠模擬直至$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}$必定不會吃)……it

換言之,$a_{n}$吃掉$a_{1}$當且僅當下一次出現$a_{n'}-a_{1}\ge a_{2}$時$n$與$n'$同奇偶,正確性能夠概括獲得,同時下一次$n-1$與$n'$就不一樣奇偶了,即不能吃掉class

如何維護這個過程,對兩部分分別維護:im

1.對於第一部分,即每一次都有$a_{n}-a_{1}<a_{2}$,將全部點分爲通過操做和未通過操做兩部分,根據上面證實的過程,越晚通過操做的越小,所以用一個隊列維護兩部分,最小值和最大值均可以獲得img

2.對於第二部分,直接令$a_{1}=a_{n}-a_{1}$便可(固然要判斷一下)di

還有一些特殊狀況,主要是關於$n=2$時的判斷view

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$

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk= watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
 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\n",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\n",calc(n));
65     }
66     return 0;
67 }
View Code
相關文章
相關標籤/搜索