题意:把所有的科学家的题目进行输入,要求使得释放资源最少,而且使得科学家所有输入的题目的相对顺序不能改变。出现逆序对的原因是对之前的资源处理时,%m,所以可能会出现逆序对的情况。对于前面一个问题,就是按照输入的题目优化后所得到的逆序对是最少的,而且每个科学家输入的题目相对顺序不能变。所以当把所有的题目合并的时候,优化后的最少逆序对就是所有科学家中逆序对数最多的逆序对数,因为在合并所有的题目的时候,按照最大的逆序对数来划分段,然后在把其他的科学家的题目相对应的段插到一起,因为每个段都是有序的,所以插入进来后每个段也是有序的,所以优化后的逆序对数就是之前所有科学家的最大的逆序对数。
思路:首先会输入第一个数据,然后依次统计后面的情况,使用逆序对数来作为段的段号,当然会使用段号来进行排序,
主要是统计每个科学家的逆序对数以此作为段的数目,还有就是要统计总的题目数,超过200000的时候,就不用往数组里面添加了,(一定要判断,否则有一部分通不过),只统计总的逆序对数就可以了。
参考:https://blog.youkuaiyun.com/myfatmyfat/article/details/88205053
代码:
#include <iostream>
#include<algorithm>
#include<vector>
typedef long long int LL;
#define N 200000
using namespace std;
struct node{
LL section,res,index;//section(切段后的段号),res(所需资源号),index(科学家的编号)
node(){}
node(LL s,LL r,LL i):section(s),res(r),index(i){}//构造函数
}sc[210000];
bool com(node a,node b){
if(a.section != b.section)return a.section < b.section;//断号小的排在前面,毕竟先输入
else if(a.res != b.res)return a.res < b.res;//同一段中所需资源越小,越靠前
else return a.index < b.index;//所有的都一样,则需要按照科学家的索引来排序
}
int main(int argc, char** argv) {
LL n,cnt = 0,sumBad = 0;//sum保存的是所有科学家总的问题数目,sumBad表示总的逆序对数
cin>>n;
for(int i=1;i<=n;i++){
LL k,res,x,y,m,tem,badPair = 0;//badPair当前科学家的逆序对数
cin>>k>>res>>x>>y>>m;
sc[cnt++] = node(badPair,res,i); //输入第一个所需资源数
for(int j=2;j<=k;j++){
tem = (res*x+y)%m;//当前所需资源数
if(tem < res) {//当发现逆序对时,段区要改变了,badPair充当了段区的索引
badPair++;
}
if(cnt <= N){
sc[cnt++] = node(badPair,tem,i);
}
res = tem;//更新当前值
}
sumBad = max(badPair,sumBad);
}
printf("%d\n",sumBad);
sort(sc,sc+cnt,com);
if(cnt <= N){//小于N才打印,否则只打印逆序对数
for(int i=0;i<cnt;i++){
printf("%d %d\n",sc[i].res,sc[i].index);
}
}
return 0;
}