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(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现