4.15hut21
本题需要挖掘性质。
1.注意到x的交换条件,知道x每次交换后都会变大,而序列最终要非递减
所以对于所有需要交换的数,其交换顺序一定是从左至右。
2.如果序列需要交换,那么交换后序列一定是加入了一个x,失去了原有的一个数,同时对于一个确定成员的序列,其非递减序列是唯一的。
又n非常小,所以我们可以枚举假设失去的是某个数,再对新数组b排序,从左往右扫(因为必然先交换前面的),与原数组a只要不同,
那么必然需要交换,同时第一个不同的位置i,b[i]必须为x,因为这是第一个交换的地方,交换后x变为a[i],同理下一个不同的位置j,b[j]必须等于a[i]
最终x应该等于我们失去的那个数,注意每个位置判断一下b[i]是否小于a[i],否则该交换是非法的。
#include<bits/stdc++.h> using namespace std; #define endl '\n' typedef long long LL; typedef pair<int,int> PII; const int INF=0x3f3f3f3f; int n,x; bool fun(vector<int>&a,int idx,int &cnt){ vector<int>b=a; b[idx]=x; sort(b.begin(),b.end()); int last=x; for(int i=0;i<n;i++){ if(a[i]!=b[i]){ if(b[i]==last&&last<a[i])last=a[i],cnt++; else return false; } } return last==a[idx]; } void solve(){ cin>>n>>x; vector<int>a(n); bool inc=true; for(int i=0;i<n;i++){ cin>>a[i]; if(i&&a[i]<a[i-1])inc=false; } if(inc){ cout<<0<<endl; return; } int ans=INF; for(int i=0;i<n;i++){ int t=0; if(fun(a,i,t))ans=min(ans,t); } if(ans==INF)ans=-1; cout<<ans<<endl; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int T; cin>>T; while(T--){ solve(); } return 0; }
别人的贪心做法有点看不懂www,只能写暴力一点的做法。
容易陷入求路径,再排除重复的想法中。
实际上我们可以从考虑这些路径能够达到哪些元素和出发,由于相邻大小的数字在位置上也是相邻的,所以我们很容易的发现能构成的值是一个区间。
数量就是最大值与最小值的差加1。
通过数学推导可知最大值减最小值=dx*dy,所以ans=dx*dy+1;
#include<bits/stdc++.h> using namespace std; #define endl '\n' typedef long long LL; typedef pair<int,int> PII; const int INF=0x3f3f3f3f; void solve(){ LL x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; LL dx=abs(x1-x2),dy=abs(y1-y2); cout<<dx*dy+1<<endl; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int T; cin>>T; while(T--){ solve(); } return 0; }