C++,codeforces,2072D,D. For Wizards, the Exam Is Easy, but I Couldn't Handle It

/*
codeforces,2071D,D. For Wizards, the Exam Is Easy, but I Couldn't Handle It
一个数组中的逆序对是指一对数i,j(i<j)满足arr[i]>arr[j]
给定一个数组, 可进行一次操作,将数组中的一段子数组中头部的数移动到尾部,其它数向前移动,
例如选定下标l,r的子数组,将arr[l]移动到arr[r]的后面,则原数组为[a1,a2,…,al−1,al,al+1,…,ar−1,ar,ar+1,…,an−1,an]
,操作后的数组为[a1,a2,…,al−1,al+1,al+2,…,ar−1,ar,al,ar+1,…,an−1,an]
问选取怎样的l和r能使得一次操作后的数组中逆序对数量最少
*/
/*
题目中指定的操作实际是将数组中某个数移动到该数后面的某个位置
对于一个特定的数,应该将其移动到后面哪个位置取决于后面数字的大小分布
将该特定数向后移动的过程中,每经过一个小于本身的数,则能减少一个逆序对,每经过一个大于本身的数,则能增加一个逆序对
因此,对于一个特定的数,应该将其移动到后面的某位置,在该位置,若再向后面移动,无论移动到后面哪个位置,都会增加逆序对而不会减少
而这个特定的数应该是从哪些数中选取
再一个递增的子数组内部,应该移动的数是尾部的数,因为前面的数在向后移动的过程中,经过该子数组本身时只会增加逆序对
将原数组分成一段一段递增的子数组,每段子数组内部是递增的,子数组尾部的数小于下一段子数组头部的数
对所有的子数组,判断尾部的数应该移动到哪个位置,使得逆序对数量最少,并记录减少的逆序对数量
最后统计减少逆序对数量最多的子数组,输出对应的l,r
*/
#include <iostream>
#include <vector>
struct ReductionInfo{
int r;
int maxReduce;
int nextReduce;
};
void solve(){
int n;std::cin>>n;
std::vector<int> arr(n);std::cin>>arr[0];
std::vector<int> ls;
std::vector<ReductionInfo> rs;
for(int i=1;i<n;++i){
std::cin>>arr[i];
if(arr[i]<arr[i-1]){
ls.push_back(i-1);
rs.push_back({i-1,0,0});
}
for(int j = 0;j<ls.size();++j){
if(arr[i]<arr[ls[j]]){
rs[j].nextReduce++;
}else if(arr[i]>arr[ls[j]]){
rs[j].nextReduce--;
}
if(rs[j].nextReduce>0){
rs[j].maxReduce = rs[j].maxReduce+rs[j].nextReduce;
rs[j].nextReduce = 0;
rs[j].r = i;
}
}
}
if(ls.size()==0){
std::cout<<"1 1"<<std::endl;
}else{
int maxReduce = rs[0].maxReduce,maxIndex = 0;
for(int i = 1;i<rs.size();++i){
if(rs[i].maxReduce>maxReduce){
maxReduce = rs[i].maxReduce;
maxIndex = i;
}
}
std::cout<<ls[maxIndex]+1<<" "<<rs[maxIndex].r+1<<std::endl;
}
}
int main(){
int t;std::cin>>t;
while(t--){
solve();
}
}
posted @   Kazuma_124  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示