XDU校赛F(贪心+优先队列)

既然代主席叫窝写题解,窝当然得好好写辣。。

原题:http://codeforces.com/gym/101498/problem/F

思路:

其实最主要的问题是在内存满的时候将谁弹出,也就是让留在内存里面的页面尽可能得发挥作用。。

怎么发挥作用?反正碰到相同页面的能发挥作用了嘛。。对内存里面的所有页面找里他下一个相同页面,删除的时候当然是删除下一个页面最远的那个啦。。

然后貌似不太靠谱?可能很多人都考虑到这种情况,例如有2个内存,请求是123122222这样的,把3打入内存时可能觉得保留2也是个不错的方案?我们不妨这么想,第3个以后的2都是上一个2所作出的贡献而不是第1个2,那这样的话内存里面的页面就只能做一次贡献,而做完贡献他们就会被新页面刷新,这样的话显然要优先保留下一个页面离得比较近的了。。。

保证优先级很显然需要用优先队列,按下一页面位置降序排列。。。然后在实现过程中刷新页面这个操作也是直接插入的,旧页面会在队尾不起作用。。。




原题的参考代码:

#include<bits/stdc++.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define inf 2147483647
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define NM 100010
#define nm 1000000
#define link(x) for(edge*j=h[x];j;j=j->next)
using namespace std;
int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	return x*f;
}





struct tmp{
	int next,t;
	bool operator<(const tmp&o)const{return next<o.next;}
}a[NM];
int n,m,h[NM],cnt,ans,c[NM],b[NM];
priority_queue<tmp>q;
bool v[NM];
bool cmp(int x,int y){
	return b[x]<b[y];
}


int main(){
	int _=read();
	while(_--){
		n=read();m=read();ans=0;mem(v);mem(h);mem(a);cnt=0;
		while(!q.empty())q.pop();
		inc(i,1,n)b[i]=read(),c[i]=i;
		sort(c+1,c+1+n,cmp);
		inc(i,1,n)if(b[c[i-1]]==b[c[i]])a[c[i]].t=a[c[i-1]].t;
		else a[c[i]].t=i;
		dec(i,n,1){
			a[i].next=h[a[i].t]?h[a[i].t]:n+1;
			h[a[i].t]=i;
		}
		inc(i,1,n){
			if(v[a[i].t]){
				q.push(a[i]);
				continue;
			}
			if(cnt==m){
				tmp t=q.top();q.pop();
				v[t.t]=false;cnt--;
			}
			q.push(a[i]);cnt++;ans++;v[a[i].t]++;
		}
		printf("%d\n",ans);
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/qkoqhh/article/details/80048170