版权声明:本文为DyingShu原创文章,转载请注明出处哦。 https://blog.csdn.net/DyingShu/article/details/82251208
传送门
题目大意:模拟一个内存系统。
题解:大力Hash+线段树。
Hash记录元素是否存在,线段树寻找访问次数最少的页码。
用指针板线段树卡了卡常,居然混到BZOJ的rank1了OvO
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 10001;
const int MAXM = 1000001;
const int MOD = 1000007;
int n, m;
int Ans;
struct Node{
int l, r;
int Val, Pos, Tim, Page; //访问次数/位置/时间/现在存的页
Node *left, *right;
Node(){
l = r = Pos = Tim = Page = 0;
left = right = NULL;
}
}t[100001];
int tot;
Node *root;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
int k = 0; char ch = nc();
while(ch < '0' || ch > '9') ch = nc();
while(ch >= '0' && ch <= '9') k = (k << 3) + (k << 1) + ch - 48, ch = nc();
return k;
}
struct HASH{
int Val[MAXM], Pos[MAXM], Tag[MAXM], fir[MOD + 5], nxt[MAXM], cnt;
inline void Init(){memset(fir, -1, sizeof(fir));}
inline void Insert(int v, int pos){
for(int i = fir[v % MOD]; i != -1; i = nxt[i]){
if(Val[i] == v){Tag[i] = 1, Pos[i] = pos; return;}
}
Pos[cnt] = pos; Val[cnt] = v; Tag[cnt] = 1;
nxt[cnt] = fir[v % MOD]; fir[v % MOD] = cnt++;
}
inline int Find(int v){ //查找值为v的数,返回内存页位置
for(int i = fir[v % MOD]; i != -1; i = nxt[i]){
if(Val[i] == v) if(Tag[i]) return Pos[i];
}
return -1;
}
inline void Delete(int v){
for(int i = fir[v % MOD]; i != -1; i = nxt[i]){
if(Val[i] == v){Tag[i] = 0; return;}
}
}
}Hash;
#define mid ((u->l + u->r) >> 1)
inline void Pushup(Node *u){
if(u->left->Val != u->right->Val){
if(u->left->Val > u->right->Val){
u->Val = u->right->Val;
u->Tim = u->right->Tim;
u->Pos = u->right->Pos;
u->Page = u->right->Page;
}
else{
u->Val = u->left->Val;
u->Tim = u->left->Tim;
u->Pos = u->left->Pos;
u->Page = u->left->Page;
}
}
else{
if(u->left->Tim > u->right->Tim){
u->Val = u->right->Val;
u->Tim = u->right->Tim;
u->Pos = u->right->Pos;
u->Page = u->right->Page;
}
else{
u->Val = u->left->Val;
u->Tim = u->left->Tim;
u->Pos = u->left->Pos;
u->Page = u->left->Page;
}
}
}
inline void Build(Node *u, int l, int r){
u->l = l, u->r = r; if(l == r){u->Pos = l; return;}
u->left = &t[tot++], u->right = &t[tot++];
Build(u->left, l, mid), Build(u->right, mid + 1, r);
Pushup(u);
}
inline void Modify(Node *u, int x, int tim, int page){
if(u->l == u->r){u->Tim = tim, u->Val = 1, u->Page = page; return;}
if(x <= mid) Modify(u->left);
else Modify(u->right);
Pushup(u);
}
inline void Add(Node *u, int x){
if(u->l == u->r){u->Val++; return;}
if(x <= mid) Add(u->left); else Add(u->right);
Pushup(u);
}
#undef mid
int main(){
n = read(), m = read();
Hash.Init();
root = &t[tot++]; Build(root, 1, n);
for(register int i = 1; i <= m; ++i){
int Val = read(); //读入第i条操作
int k = Hash.Find(Val);
if(k != -1){Add(root, k); Ans++;}
else{
if(root->Page) Hash.Delete(root->Page);
Hash.Insert(Val, root->Pos);
Modify(root, root->Pos, i, Val);
}
}
printf("%d", Ans);
return 0;
}
没过之前调了很久的代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 10001;
const int MAXM = 1000001;
const int MOD = 1000007;
int n, m;
int Ans;
int cur;
bool flag;
struct Node{
int Val, Pos, Tim, Page; //访问次数/位置/时间/现在存的页
}t[MAXN << 2];
//int Now[MAXN]; //现在存的页
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
int k = 0; char ch = nc();
while(ch < '0' || ch > '9') ch = nc();
while(ch >= '0' && ch <= '9') k = (k << 3) + (k << 1) + ch - 48, ch = nc();
return k;
}
struct HASH{
int Val[MOD + 5], Pos[MOD + 5], Tag[MOD + 5], fir[MOD + 5];
int nxt[MOD + 5], cnt;
inline void Init(){memset(fir, -1, sizeof(fir));}
inline void Insert(int v, int pos){
// printf("v = %d, fir = %d\n", v, fir[v % MOD]);
for(int i = fir[v % MOD]; i != -1; i = nxt[i]){
// printf("Val = %d\n", Val[i]);
if(Val[i] == v){Tag[i] = 1, Pos[i] = pos; return;}
}
// printf("???");
// Val[cnt] = v, Tag[cnt] = 1, nxt[cnt] = fir[v % MOD], fir[v % MOD] = cnt++;
Pos[cnt] = pos; Val[cnt] = v; Tag[cnt] = 1;
nxt[cnt] = fir[v % MOD]; fir[v % MOD] = cnt++;
}
/*inline bool Find(int v){ //查找值为v的数是否存在
// printf("v = %d, fir = %d\n", v, fir[v % MOD]);
for(int i = fir[v % MOD]; i != -1; i = nxt[i]){
// printf("Val = %d, v = %d\n", Val[i], v);
if(Val[i] == v) if(Tag[i]) return true;
}
return false;
}*/
inline int Find(int v){ //查找值为v的数,返回内存页位置
// printf("v = %d, fir = %d\n", v, fir[v % MOD]);
for(int i = fir[v % MOD]; i != -1; i = nxt[i]){
// printf("Val = %d, v = %d\n", Val[i], v);
if(Val[i] == v) if(Tag[i]) return Pos[i];
}
return -1;
}
inline void Delete(int v){
// printf("!!v = %d\n", v);
for(int i = fir[v % MOD]; i != -1; i = nxt[i]){
if(Val[i] == v){Tag[i] = 0; return;}
}
}
}Hash;
struct Segmemnt_Tree{
#define mid ((l + r) >> 1)
inline Node Min(Node a, Node b){
// if(a.Pos == 4 && b.Pos == 5){
// printf("%d %d\n", a.Page, b.Page);
// printf("%d %d\n", a.Tim, b.Tim);
// printf("%d %d\n", a.Val, b.Val);
// printf("\n");
// }
// if(a.Val == b.Val) return a.Tim < b.Tim ? a : b; //时间早的
// return a.Val < b.Val ? a : b; //访问次数少的
if(a.Val != b.Val) return a.Val < b.Val ? a : b; //访问次数少的
return a.Tim < b.Tim ? a : b; //时间早的
}
inline void Build(int u, int l, int r){
if(l == r){t[u].Pos = l, t[u].Tim = t[u].Val = t[u].Page = 0; return;}
Build(u << 1, l, mid), Build(u << 1 | 1, mid + 1, r);
t[u] = Min(t[u << 1], t[u << 1 | 1]);
}
inline void Modify(int u, int l, int r, int x, int tim, int page){
if(l == r){
// printf("")
// printf("t[u].Pos = %d\n", t[u].Pos);
// if(t[u].Val){
// printf("!");
// Hash.Delete(Now[t[u].Pos]);
// }
if(t[u].Page) Hash.Delete(t[u].Page);
t[u].Tim = tim, t[u].Val = 1, t[u].Page = page;
// printf("tim[%d] = %d\n", Now[x], tim);
// printf("t[u].Pos = %d\n", t[u].Pos);
return;
}
if(x <= mid) Modify(u << 1, l, mid, x, tim, page);
else Modify(u << 1 | 1, mid + 1, r, x, tim, page);
t[u] = Min(t[u << 1], t[u << 1 | 1]);
}
inline void Add(int u, int l, int r, int x){
if(l == r){
t[u].Val++;
// if(t[u].Page == 10){
// printf("~%d %d\n", t[u].Page, t[u].Val);
// }
return;
}
if(x <= mid) Add(u << 1, l, mid, x);
else Add(u << 1 | 1, mid + 1, r, x);
t[u] = Min(t[u << 1], t[u << 1 | 1]);
}
#undef mid
}T;
int main(){
n = read(), m = read();
Hash.Init(); T.Build(1, 1, n);
for(int i = 1; i <= m; i++){
int Val = read(); //读入第i条操作
// printf("Min = %d, Now = %d\n", t[1].Pos, Now[t[1].Pos]);
int k = Hash.Find(Val);
// printf("Val = %d, k = %d\n", Val, k);
// if(Hash.Find(Val)){//a
if(k != -1){//a
// printf("i = %d, Val = %d, k = %d\n", i, Val, k);
T.Add(1, 1, n, k);
Ans++;
// printf("\n");
// continue;
}
else{
// int c = Hash.Find(Val);
// printf("c = %d\n", c);
// Node Tmp;
// if(cur + 1 <= n){ //b
// cur++;
// printf("cur = %d\n", cur);
// Hash.Insert(Val, cur);
// Tmp.Pos = cur, Tmp.Tim = i, Tmp.Val = 1;
// T.Modify(1, 1, n, cur, Tmp);
// }
// else{ //c
// printf("Val = %d\n", Val);
int P = t[1].Pos;
// printf("k = %d, last = %d\n", k, Now[k]);
// Hash.Delete(Now[k]); //删除
// Tmp.Pos = k, Tmp.Tim = i, Tmp.Val = 1;
Hash.Insert(Val, P);
T.Modify(1, 1, n, P, i, Val);
// Now[k] = Val;
// }
}
// printf("i = %d, val = %d, Ans = %d\n", i, Val, Ans);
// printf("\n");
}
printf("%d", Ans);
return 0;
}