A. False Alarm
只有当遇到关着的门才需要使用能力,标记最左侧关着的门为l,最右侧的关着的门为r,那么如果r-l+1>x则不能通过。
1 #include <iostream> 2 using namespace std; 3 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 4 5 const int N = 15; 6 int q[N]; 7 int main(int argc, char** argv) { 8 int t; 9 cin>>t; 10 while(t--){ 11 int n,x; 12 cin>>n>>x; 13 for(int i=0;i<n;i++) 14 cin>>q[i]; 15 int l=-1,r=n; 16 for(int i=0;i<n;i++) 17 if(q[i]==1){ 18 l=i; 19 break; 20 } 21 for(int i=n-1;i>=0;i--){ 22 if(q[i]==1){ 23 r=i; 24 break; 25 } 26 } 27 if(r-l+1>x) 28 cout<<"No"<<endl; 29 else 30 cout<<"Yes"<<endl; 31 } 32 return 0; 33 }
B. Shrink
构造题,每次能够删除一个a[i],如果a[i]>a[i-1]&&a[i]>a[i+1],给定一个n,让我们构造一个能够删除最多的元素的长度为n的序列。
那么我们只需要按照1,n,(n-1),(n-2)....2的顺序排布,就可以保证序列能够删除n-2个元素。
1 #include <iostream> 2 using namespace std; 3 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 4 5 int main(int argc, char** argv) { 6 int t; 7 cin>>t; 8 while(t--){ 9 int n; 10 cin>>n; 11 cout<<1<<" "; 12 for(int i=n;i>=2;i--){ 13 cout<<i<<" "; 14 } 15 cout<<endl; 16 } 17 return 0; 18 }
C. Cool Partition
给定一个序列,问这序列至多分为多少段,能够保证在前一段出现过的元素都在后一段中出现。
显然第一段只有一个元素是将该序列分为最多段数的一个解,那么我们从第二段开始保证前一段的元素全部出现过即可。
1 #include <iostream> 2 #include <set> 3 using namespace std; 4 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 5 6 const int N = 2e5+10; 7 int a[N]; 8 9 int main(int argc, char** argv) { 10 int t; 11 cin>>t; 12 while(t--){ 13 int n; 14 cin>>n; 15 for(int i=1;i<=n;i++) cin>>a[i]; 16 int res=1; 17 set<int> S; 18 int start=2; 19 S.insert(a[1]); 20 for(int i=2;i<=n;i++){ 21 if(S.count(a[i])){ 22 S.erase(a[i]); 23 } 24 if(S.size()==0){ 25 res++; 26 for(int j=start;j<=i;j++) 27 S.insert(a[j]); 28 start=i+1; 29 } 30 } 31 cout<<res<<endl; 32 } 33 return 0; 34 }
D. Retaliation
给定一个序列,操作1是对整个序列的每个元素减去i,操作2是对整个序列的每个元素减去(n-i+1),问是否能够通过这两个操作将序列变为全0。
我们从全零反向考虑,如果操作一和操作二成对出现,则每个元素的值都相等,而且(n+1)|a[i],每个元素都是(n+1)的倍数。此时在加上若干操作1或者操作2。
举个例子,序列21 18 15 12 9,都减去n+1,得15 12 9 6 3,此时就是三次操作2得到的,可以注意到,操作2的次数,和相邻元素的差值绝对值是相等的,因为每次操作会让此差值加一。
1 #include <iostream> 2 #include <set> 3 #include <algorithm> 4 #define x first 5 #define y second 6 using namespace std; 7 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 8 typedef pair<int,int> PII; 9 const int N = 2e5+10; 10 int a[N]; 11 int n; 12 13 int main(int argc, char** argv) { 14 int t; 15 cin>>t; 16 while(t--){ 17 cin>>n; 18 for(int i=1;i<=n;i++){ 19 cin>>a[i]; 20 } 21 int k=a[2]-a[1];//k>0表明多余的操作为op1,否则为op2 22 int cnt=abs(k); 23 if(k<0){ 24 for(int i=1;i<=n;i++){ 25 a[i]-=cnt*(n-i+1); 26 } 27 }else if(k>0){ 28 for(int i=1;i<=n;i++){ 29 a[i]-=k*i; 30 } 31 } 32 //接下来剩余的所有元素应该相等而且(n+1)|a[i],因为两个操作成对出现 33 bool flag=a[1]%(n+1)==0&&a[1]>=0;//k次操作1或操作2后不能有负值 34 for(int i=2;i<=n;i++){ 35 if(a[i]!=a[i-1]||a[i]%(n+1)){ 36 flag=false; 37 break; 38 } 39 } 40 if(!flag){ 41 cout<<"No"<<endl; 42 }else{ 43 cout<<"Yes"<<endl; 44 } 45 46 } 47 return 0; 48 }
浙公网安备 33010602011771号