4.15hut21

D. Sequence and Swaps

本题需要挖掘性质。

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,只能写暴力一点的做法。

G.Celex Update

容易陷入求路径,再排除重复的想法中。

实际上我们可以从考虑这些路径能够达到哪些元素和出发,由于相邻大小的数字在位置上也是相邻的,所以我们很容易的发现能构成的值是一个区间。

数量就是最大值与最小值的差加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;
}

 

posted @ 2023-04-22 22:08  星陨光逝  阅读(13)  评论(0编辑  收藏  举报