洛谷1338:
题意:给n个数: 1- n,已知逆序数为m,输出最小字典序的排列
用ans存数组
#include<iostream>
#include<algorithm>
using namespace std;
long long int n;
//试了几次 这个n一定要开 long long why??
long long m;
int a[50005];
int main(){
cin>>n>>m;
//如果装不下,放最后一个
//其实是这样 判断每一位数字的时候 ,已知 长度为l最多贡献(l+1)(l)/2的逆序
//中间有一位的数字是不定的,相当于一个突跃点,这个点前面是升序,后面是根据逆序数排成的
// 1 2 3 x 后面再排
//装得下 放第一个(为了字典序最小);装不下的时候,放最后一个,这样最优(??)
//emmm这样可以贡献更多的逆序数,来满足字典序最小
int head=1;int tail=n;
for( int i=1;i<=n;i++){
long long t=(n-i)*(n-i-1)/2;
if(t>=m){
a[head++]=i;
}
else{
a[tail--]=i;
m-=(tail-head+1);
}
}
for(int i=1;i<=n;i++){
cout << a[i]<<" ";
}
}
2.昨天看到的一个神秘排序
排序时必须放到队首,可见最大次数为n-1次(倒序)求最小操作次数
怎么像匹配呢??这是什么原理啊。
#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
using namespace std;
int n,t;
int a[100005],b[100005];
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
cin >> a[i];
b[i]=a[i];
}
//1 3 2 4 ans: 3
// b 1234
// a 1324
sort(b+1,b+1+n);
int ans = 0;
for(int i=n;i>=1;i--){
if(b[i+ans]==a[i]){
continue;
}
else ans++;
}
cout << ans <<endl;
}}
2.洛谷P2661 信息传递
#include <cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<string>
#include<stack>
using namespace std;
int n,ans=0x3f3f3f;
//fir存储的是第一次经过该节点的序号,那么成环时
//大小 = 遍历序号-fir[node]
int nxt[200005],fir[200005];
//vis是否访问过, forevis:是否已经搜过
bool vis[200005],forevis[200005];
void dfs(int node,int c){
if(forevis[node]) return ;
//成环
if(vis[node]){
ans = min(ans,c-fir[node]);
return;
}
vis[node]=1;
fir[node]=c;
dfs(nxt[node],c+1);
forevis[node]=1;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>nxt[i];
for(int i=1;i<=n;i++){
dfs(i,0);
}
cout << ans << endl;
return 0;
}