题解 P4404 【[JSOI2010]缓存交换】

SuperJvRuo

2018-07-14 09:26:30

Solution

~~可以证明,~~每一次从cache中删除的主存一定是下次访问最晚的,可以用优先队列维护。 首先当然是要离散化。先倒着扫一遍建出链式结构,再正着扫一遍模拟访问过程,具体实现看代码。 ``` #include<cstdio> #include<cctype> #include<cstring> #include<algorithm> #include<queue> using std::pair; using std::priority_queue; typedef pair<int, int> opt; //first表示下一次访问该主存的时间,second表示这块主存离散化后的序号 int Read() { int x = 0; char c = getchar(); while (!isdigit(c)) { c = getchar(); } while (isdigit(c)) { x = (x << 3) + (x << 1) + (c ^ 48); c = getchar(); } return x; } int next_query[100005], first_query[100005]; //next_query[opt]表示下一个 与opt使用相同主存的 操作 //first_query[mem]表示 下一次对mem的 操作 void Add_opt(int memory, int order)//构建上边两个数组 { next_query[order] = first_query[memory]; first_query[memory] = order; } void Do_opt(int memory)//维护上边first_query数组 { first_query[memory] = next_query[first_query[memory]]; } int memory[100005], number[100005]; bool inCache[100005];//这块主存是否在cache中 int main() { memset(first_query, 0x3f, sizeof(first_query)); int n = Read(), m = Read(); for (int i = 1; i <= n; ++i) { memory[i] = Read(); number[i] = memory[i]; } std::sort(number + 1, number + n + 1); int size = std::unique(number + 1, number + n + 1) - number - 1; //离散化,从后往前建出每块主存的操作顺序 for (int i = n; i >= 1; --i) { Add_opt(memory[i] = std::lower_bound(number + 1, number + size + 1, memory[i]) - number, i); } int ans = 0; //从前往后贪心操作 priority_queue<opt> cache;//这个单词的读音同cash,不读catch for (int i = 1; i <= n; ++i) { if (!inCache[memory[i]]) { ++ans;//miss了一次 if (cache.size() == m)//cache满了 { inCache[cache.top().second] = 0; cache.pop();//移除下次操作最远的主存 } Do_opt(memory[i]);//进行操作 inCache[memory[i]] = 1; cache.push(opt(first_query[memory[i]], memory[i])); } else { Do_opt(memory[i]); ++m; //std::priority_queue不能modify,那就再push一次,同时让大小限制+1 //之前对这块主存的操作的first 一定小于 新push进去的操作的first //所以对贪心没有影响 cache.push(opt(first_query[memory[i]], memory[i])); } } printf("%d", ans); return 0; } ```