玲珑OJ 1045 - I. Quailty and LRU Algorithm 模拟双向链表

来源:互联网 发布:盛发软件 编辑:程序博客网 时间:2024/06/05 02:08



链接:戳这里


1045 - I. Quailty and LRU Algorithm
Time Limit:2s Memory Limit:128MByte


DESCRIPTION
Quailty is learning a type of page replacement algorithm for memory management in operation system, LRU(Least Recently Used) algorithm.

To help Quailty understand this algorithm, you are asked to implement this algorithm for him. The following is a brief introduction of this algorithm.

Initially, you have an empty queue to store some addresses of pages temporarily, where the size of the queue must less than or equal to 
n
n.

When a page which is not in the queue is required to be loaded, pop the front element of the queue and push this page to the tail of the queue if the queue is full, push this page to the tail directly otherwise.

When a page which is in the queue is required to be loaded, just move this page to the tail of the queue.


In this problem, Quailty has 
q
q requires. Each require contains a non-negative integer 
x
x, which represents that the page whose address is 
x
x is required to be loaded, and you are asked to calculate the sum of the addresses in the queue after each require finished.

SAMPLE INPUT
2
5 10
0 1 1 5
5 10
0 1 1 10
SAMPLE OUTPUT
485
1135


题意:

抽象一下题意把

给出n个数,然后插入队列

1:当前数在队列里,则将这个数放置队尾

2:这个数不在队列里,插入队尾

3:当队列满了,也就是队列里的数个数为n,则新插入一个人数,需要删除对首,队尾插入新数

每次都拿i*队列总数和


思路:

模拟链表然后实现过程,具体看代码


stl里的list实现的T的代码,list::remove()的复杂度是On

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include <ctime>#include<queue>#include<set>#include<map>#include <list>#include<stack>#include<iomanip>#include<cmath>#define mst(ss,b) memset((ss),(b),sizeof(ss))#define maxn 0x3f3f3f3f#define MAX 1000100///#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;typedef unsigned long long ull;using namespace std;int n,q;list<int> L;int vis[1000010];int x,A,B,P;ull ans,sum;int main(){    int T;    scanf("%d",&T);    while(T--){        L.clear();        mst(vis,0);        scanf("%d%d",&n,&q);        scanf("%d%d%d%d",&x,&A,&B,&P);        sum=ans=0;        for(int i=1;i<=q;i++){            if(vis[x]){                L.remove(x);                L.push_back(x);            } else {                if(L.size()==n){                    int tmp=*L.begin();                    L.pop_front();                    vis[tmp]=0;                    sum-=tmp;                }                sum+=x;                L.push_back(x);                vis[x]=1;            }            ans+=i*sum;            x=(1LL*x*A+B)%P;        }        printf("%llu\n",ans);    }    return 0;}



AC代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include <ctime>#include<queue>#include<set>#include<map>#include <list>#include<stack>#include<iomanip>#include<cmath>#define mst(ss,b) memset((ss),(b),sizeof(ss))#define maxn 0x3f3f3f3f#define MAX 1000100///#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;typedef unsigned long long ull;using namespace std;int n,q;int vis[1000010];int x,A,B,P;ull ans,sum;int L[1000100],R[1000100];int main(){    int t;    scanf("%d",&t);    while(t--){        mst(vis,0);        mst(L,0);        mst(R,0);        scanf("%d%d",&n,&q);        scanf("%d%d%d%d",&x,&A,&B,&P);        sum=ans=0;        int cnt=0;        int S=P,T=P+1;        R[S]=T;L[T]=S;        for(int i=1;i<=q;i++){            if(!vis[x]){                if(cnt==n){                    /*                    当前队列满了,头部删掉尾部插入新数                    队头的左边的右边指向队头的右边                    队头的右边的左边指向队头的左边                    */                    int tmp=R[S];                    L[R[tmp]]=S;                    R[P]=R[tmp];                    sum-=tmp;                    vis[tmp]=0;                    cnt--;                }                /*                当前插入新的数,新的数左边指向队尾的左边,新的数右边指向队尾                新的数右边的左边和新的数左边的右边指向x                */                L[x]=L[T];                R[x]=T;                R[L[x]]=x;                L[T]=x;                cnt++;                sum+=x;                vis[x]=1;            } else {                /*                当前插入的x已经存在,需要模拟删除                当前的x的左边指向x的右边                当前的x的右边指向x的左边                */                R[L[x]]=R[x];                L[R[x]]=L[x];                /*                当前插入新的数,新的数左边指向队尾的左边,新的数右边指向队尾                新的数右边的左边和新的数左边的右边指向x                */                L[x]=L[T];                R[x]=T;                R[L[x]]=x;                L[R[x]]=x;            }            x=(1LL*A*x+B)%P;            ans+=1LL*i*sum;        }        printf("%llu\n",ans);    }    return 0;}


0 0