CF1746C(构造)
https://codeforces.com/contest/1746/problem/c
题意
给一个排列,进行 \(n\) 次操作,第 \(i\) 次操作可以将任意指定长度的后缀加 \(i\)。问经过 \(n\) 次操作后,能使逆序最小的操作方案。
思路
首先可以发现,后面的数一定比前面的数有更多的增量,所以若干次操作不会让后缀产生新的逆序,每次操作只会让逆序数不增。于是,我们只需要考虑操作一次后和前缀的关系。
然后如果我们每次只考虑增量区间的端点,\(n\) 次操作可以构造出 \(n\) 个 \(n+1\) 。当然这是在不考虑区间加,仅考虑每次操作对端点的影响,但是又由于上面说的,每次操作不会对后缀产生新的逆序,于是忽略除端点外的区间是可行的。
于是,构造单点更新情况下的 \(n\) 个 \(n+1\)就可以得到答案。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<bitset>
#include<queue>
#include<map>
#include<stack>
#include<string>
#include<random>
#include<cassert>
#include<functional>
#include<iomanip>
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3fll
#define endl '\n'
#define ll long long
#define int long long
#define SZ(x) (int)x.size()
#define rep(i,a,n) for(int i = (a);i <= (n);i++)
#define dec(i,n,a) for(int i = (n);i >= (a);i--)
using namespace std;
using PII = array<int,2>;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
const int N =10 + 2e5 ,mod=1e9 + 7;
void solve() {
int n; cin >> n;
vector<int> a(n + 1); rep(i, 1, n) cin >> a[i];
vector<int> ans(n + 1);
rep(i, 1, n) {
ans[n - a[i] + 1] = i;
}
rep(i, 1, n) cout << ans[i] << " \n"[i == n];
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--)
solve();
return 0;
}
标签:CF1746C,int,rep,构造,long,操作,include,define
From: https://www.cnblogs.com/Mxrush/p/16796880.html